ImportSelector例子
配置类
@ComponentScan("com.lry")
@Configuration//加了全配置注解会被cglib增强
@Import(MyImportSelector.class)
//@Conditional(MyCondition.class)这个条件不满足的话不会去扫描com.lry包
public class AppConfig {
}
入口类
public static void main(String[] args) {
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(AppConfig.clas);
}
ImportSelector
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{UserService.class.getName(), OrderService.class.getName()};
}
}
两个服务类
public class OrderService {//注意不要加Service注解
}
public class UserService {//注意不要加Service注解
}
源码解析
剑指spring二详细解析了bean工厂后置处理器的执行,但是在解析配置类的时候限于篇幅没有展开ImportSelector来说,故这里做一个补充。
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
for (SourceClass candidate : importCandidates) {
//candidate是MyImportSelector对应的SourceClass 文件
//处理ImportSelector
if (candidate.isAssignable(ImportSelector.class)) {
//MyImportSelector class文件
Class<?> candidateClass = candidate.loadClass();
//BeanUtils根据class文件创建对象,可以理解selector 是MyImportSelector的对象
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
//这里可以忽略,没有实现Aware接口
ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader,this.registry);
if (selector instanceof DeferredImportSelector) {//不延迟处理
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}else {
//importClassNames有两个元素,一个是UserService,一个是OrderService
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
//将这两个类利用asm技术变成SourceClass集合
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
//可以看到递归调用了,但是递归后处理的就是普通的类了,在这里是UserService,OrderService,这两个类都没有加注解
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
}
}