剑指spring源码(二)补充篇之ImportSelector

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);
					}
				}
		}
}