1. 程式人生 > 其它 >ioc原理3 :自定義匯入器

ioc原理3 :自定義匯入器

技術標籤:筆記javaspring

問題引入
在通常情況下,bean只有通過配置才可以進入spring容器,被spring載入並控制
配置bean的方式如下:
1.XML檔案方式配置
2.使用註解方式配置
然而? 如果現在由大量的bean需要配置,那麼需要一個一個去配置嗎?
此時就需要一個匯入器快速高效配置大量的bean
例如:

在這裡插入圖片描述
現在這個類並沒有添加註解和配置然後將它放到spring容器中

自定義匯入器

1.定義一個類實現ImportSelector介面重寫selectImports方法

public class MyImportSelector implements ImportSelector
{ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { // 1.程式設計形式載入一個類 // return new String[]{"com.itheima.dao.impl.BookDaoImpl"}; // 2.載入import.properties檔案中的單個類名 // ResourceBundle bundle = ResourceBundle.getBundle("import");
// String className = bundle.getString("className"); // 3.載入import.properties檔案中的多個類名 ResourceBundle bundle = ResourceBundle.getBundle("import"); String className = bundle.getString("className"); return className.split(","); }
}

improt.properties
在這裡插入圖片描述

如果說需要匯入某個包下的類
path=com.itheima.dao.impl.*
匯入器工具類 複製修改配置檔名即可

public class CustomerImportSelector implements ImportSelector {

    private String expression;

    public CustomerImportSelector(){
        try {
            //初始化時指定載入的properties檔名
            Properties loadAllProperties = PropertiesLoaderUtils.loadAllProperties("import.properties");
            //設定載入的屬性名
            expression = loadAllProperties.getProperty("path");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //1.定義掃描包的名稱
        String[] basePackages = null;
        //2.判斷有@Import註解的類上是否有@ComponentScan註解
        if (importingClassMetadata.hasAnnotation(ComponentScan.class.getName())) {
            //3.取出@ComponentScan註解的屬性
            Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(ComponentScan.class.getName());
            //4.取出屬性名稱為basePackages屬性的值
            basePackages = (String[]) annotationAttributes.get("basePackages");
        }
        //5.判斷是否有此屬性(如果沒有ComponentScan註解則屬性值為null,如果有ComponentScan註解,則basePackages預設為空陣列)
        if (basePackages == null || basePackages.length == 0) {
            String basePackage = null;
            try {
                //6.取出包含@Import註解類的包名
                basePackage = Class.forName(importingClassMetadata.getClassName()).getPackage().getName();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            //7.存入陣列中
            basePackages = new String[] {basePackage};
        }
        //8.建立類路徑掃描器
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        //9.建立型別過濾器(此處使用切入點表示式型別過濾器)
        TypeFilter typeFilter = new AspectJTypeFilter(expression,this.getClass().getClassLoader());
        //10.給掃描器加入型別過濾器
        scanner.addIncludeFilter(typeFilter);
        //11.建立存放全限定類名的集合
        Set<String> classes = new HashSet<>();
        //12.填充集合資料
        for (String basePackage : basePackages) {
            scanner.findCandidateComponents(basePackage).forEach(beanDefinition -> classes.add(beanDefinition.getBeanClassName()));
        }
        //13.按照規則返回
        return classes.toArray(new String[classes.size()]);
    }
}