1. 程式人生 > >載入指定包(加深對Spring框架的理解)

載入指定包(加深對Spring框架的理解)

@[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框架判斷類物件有這種註解,它就會去例項化這個類,然後將例項化的類載入到容器中。