載入指定包(加深對Spring框架的理解)
阿新 • • 發佈:2018-12-12
@[TOC]載入指定包的類物件到容器
package com.ruoyi.project.tool.nio; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.util.HashMap; import java.util.Map; //import org.apache.ibatis.io.Resources; //import java.io.FileFilter; //import java.net.URL; /** * 載入指定包下的類 * @author David */ public class LoadClassUtils { /** * 遞迴載入類資訊 * * @param map 存放載入物件的容器map * @param file 載入的物件檔案 * @param packageName - 檔案的包名 例如com.weyao.saas(這個引數是必須要傳的,不傳的話會導致遍歷到目錄,class檔案不知道在哪個包下) * @throws ClassNotFoundException */ public static void loadBean(Map<String, Class> map, File file, String packageName) throws ClassNotFoundException { // 目錄處理 if (file.isDirectory()) { // 獲取目錄下的檔案物件資訊 File[] files = file.listFiles(new FilenameFilter() { // 對檔案進行過濾(獲取目錄及以.class結尾的檔案) @Override public boolean accept(File dir, String name) { if (file.isDirectory() || (file.isFile() && file.getName().endsWith(".class"))) { return true; } return false; } }); // 遍歷目錄下的檔案 for (File subFile : files) { // 如果是仍然是目錄 if (subFile.isDirectory()) { // 獲取目錄名稱,例如common、service這種目錄名稱 String subPackageName = subFile.getName(); loadBean(map, subFile, packageName + "." + subPackageName); } else { // 如果是.class檔案 loadBean(map, subFile, packageName); } } } else { // 判斷為檔案不再遞迴直接例項化 if (file.isFile() && file.getName().endsWith(".class")) { String fileName = file.getName(); System.out.println(fileName); System.out.println(fileName.lastIndexOf(".class")); String className = fileName.substring(0, fileName.lastIndexOf(".")); Class<?> aClass = Class.forName(packageName + "." + className); map.put(className, aClass); } } } public static void main(String[] args) throws IOException, ClassNotFoundException { String packagePath = "com.ruoyi.project"; loadSpeckLoad(packagePath); } /** * 載入指定包 * * @param packagePath * @throws IOException * @throws ClassNotFoundException */ public static void loadSpeckLoad(String packagePath) throws IOException, ClassNotFoundException { String filePath = ClassLoader.getSystemResource("com/ruoyi/project").getPath(); File packageFile = new File(filePath); Map<String, Class> map = new HashMap<>(); loadBean(map, packageFile, packagePath); for (Map.Entry<String, Class> entry : map.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); System.out.println(key + value); } } // /** // * 另一種將包名轉化檔案物件的方式(但是這個Resources是org.apache.ibatis.io包下的) // * 如果有興趣可以新增Maven依賴玩一下 // */ // public void getPackagePath(String packagePath) throws IOException, ClassNotFoundException { // URL resourceURL = Resources.getResourceURL(packagePath.replace(".","/")); // String protocol = resourceURL.getProtocol(); // if("file".equals(protocol)) { // String filePath = resourceURL.getFile(); // File packageFile = new File(filePath); // Map<String, Class> map = new HashMap<>(); // loadBean(map, packageFile, packagePath); // }else { // TODO 對jar包的解析處理 // } // } }
小結:三個關鍵點吧 1 將指定包轉換為File或轉化為Resource再轉化為File 2 對層層巢狀的檔案,需要採用遞迴(自己調自己)去處理 3 遞迴的方法中需要傳包名
意義:Spring不就有個掃描指定包的標籤嗎?例如<context:component-scan base-package="cn.edu.dao"/>
。首先通過定義這個指定包,Spring就能幫你把指定包下的定義了@Controller、@Service、@Component,@Repository的類轉化為bean物件。然後它就是通過你定義的指定包,然後幫你掃描指定包下的所有.class檔案,然後反射得到它的類物件,這樣它就掌握了這個類的所有結構資訊,當然也包括是否有@Controller、@Service這樣的註解,最後Spring框架判斷類物件有這種註解,它就會去例項化這個類,然後將例項化的類載入到容器中。