Springboot-importSelector 绝地灬酷狼 2021-09-25 13:44 194阅读 0赞 ## ImportSelector接口概述 ## 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 */ @Nullable default Predicate<String> getExclusionFilter() { return null; } } 该接口文档上说的明明白白,其主要作用是收集需要导入的配置类,selectImports()方法的返回值就是我们向Spring容器中导入的类的全类名。如果该接口的实现类同时实现EnvironmentAware, BeanFactoryAware ,BeanClassLoaderAware或者ResourceLoaderAware,那么在调用其selectImports方法之前先调用上述接口中对应的方法,如果需要在所有的@Configuration处理完在导入时可以实现DeferredImportSelector接口。 在ImportSelector接口的selectImports()方法中,存在一个AnnotationMetadata类型的参数,这个参数能够获取到当前标注@Import注解的类的所有注解信息。 ## ImportSelector接口实例 ## 首先,我们创建一个MySelector类实现ImportSelector接口,如下所示。 /** * @import 注解中使用ImportSelector * 自定义逻辑,返回需要导入的组件 */ public class MySelector implements ImportSelector { /** * 返回值为需要导入到容器中的bean的全类名数组 * @param annotationMetadata * @return */ @Override public 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 includeFilters scanner.addIncludeFilter(new AssignableTypeFilter(User.class)); //scanner.addExcludeFilter(new AssignableTypeFilter(Object.class));//这里可以实现排除,相当@ComponentScan excludeFilters Set<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]); } } Student public class Student { private String name; public Student() { this.name = "初始化数据"; } @Override public 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容器。
还没有评论,来说两句吧...