其他分享
首页 > 其他分享> > ioc原理3 :自定义导入器

ioc原理3 :自定义导入器

作者:互联网

问题引入
在通常情况下,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()]);
    }
}

标签:basePackages,String,自定义,ComponentScan,导入,new,注解,ioc,加载
来源: https://blog.csdn.net/weixin_45087693/article/details/111085986