ImportSelector接口是至spring中导入外部配置的核心接口,在SpringBoot的自动化配置和@EnableXXX(功能性注解)都有它的存在。我们先来看一下ImportSelector接口的源码,如下所示。
public interface ImportSelector {/*** Select and return the names of which class(es) should be imported based on* the {@link AnnotationMetadata} of the importing @{@link Configuration} class.* @return the class names, or an empty array if none*/String[] selectImports(AnnotationMetadata importingClassMetadata);/*** Return a predicate for excluding classes from the import candidates, to be* transitively applied to all classes found through this selector's imports.* <p>If this predicate returns {@code true} for a given fully-qualified* class name, said class will not be considered as an imported configuration* class, bypassing class file loading as well as metadata introspection.* @return the filter predicate for fully-qualified candidate class names* of transitively imported configuration classes, or {@code null} if none* @since 5.2.4*/@Nullabledefault Predicate<String> getExclusionFilter() {return null;}}
该接口文档上说的明明白白,其主要作用是收集需要导入的配置类,selectImports()方法的返回值就是我们向Spring容器中导入的类的全类名。如果该接口的实现类同时实现EnvironmentAware, BeanFactoryAware ,BeanClassLoaderAware或者ResourceLoaderAware,那么在调用其selectImports方法之前先调用上述接口中对应的方法,如果需要在所有的@Configuration处理完在导入时可以实现DeferredImportSelector接口。
在ImportSelector接口的selectImports()方法中,存在一个AnnotationMetadata类型的参数,这个参数能够获取到当前标注@Import注解的类的所有注解信息。
首先,我们创建一个MySelector类实现ImportSelector接口,如下所示。
/*** @import 注解中使用ImportSelector* 自定义逻辑,返回需要导入的组件*/
public class MySelector implements ImportSelector {/*** 返回值为需要导入到容器中的bean的全类名数组* @param annotationMetadata* @return*/@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(MyScan.class.getName());if (CollectionUtils.isEmpty(attributes)) {return new String[0];}String[] basePackages = (String[]) attributes.get("basePackages");ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);scanner.addIncludeFilter(new AssignableTypeFilter(Student.class));//这里实现包含,相当@ComponentScan includeFiltersscanner.addIncludeFilter(new AssignableTypeFilter(User.class));//scanner.addExcludeFilter(new AssignableTypeFilter(Object.class));//这里可以实现排除,相当@ComponentScan excludeFiltersSet<String> classs = new HashSet<>();for (String basePackage : basePackages) {Set<BeanDefinition> components = scanner.findCandidateComponents(basePackage);components.forEach(bean -> classs.add(bean.getBeanClassName()));}return classs.toArray(new String[0]);}
}
springboot中文手册,Student
public class Student {private String name;public Student() {this.name = "初始化数据";}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +'}';}
}
User:
@TableName(value = "user")
public class User extends BaseEntity{@TableField(value = "name")private String name;@TableField(value = "sex")private Integer sex;}
上面已经把Student、User全类名返回到MySelector类的selectImports()方法中。
运行启动类,我们会发现这两个类已经加载进Spring容器。
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态