@Import
@Import的作用主要是用来向spring容器中注入bean,对于这个注解可以添加的参数一共有三种。
- 普遍类,就是需要注入的类
- 实现ImportSelector的类
- 实现ImportBeanDefinitionRegistrar的类
对于着几种类的作用就不再这里赘述了,首先第一种就是普通的注入。
ImportSelector的实现类的作用参考ImportSelector使用——spring容器bean的注入
ImportBeanDefinitionRegistrar的作用参考spring的扩展点总结
这里探讨的是@Import的底层实现,首先我们必须明白这个注解到底是从哪里调用的,通过源码的分析,这个注解调用的入口方法就是spring上下文对象的refresh方法,这个方法可能是用户自己调用的,也可能是在调用spring上下文对象的有参构造器的时候调用的,当不论如何这个方法都是必不可少的。它是spring初始化的三大步骤之一,也是最后一个步骤。
整个的方法调用链如下,到最后是通过processImports这个方法来处理Import注解的
这个放法更多的是对ImportSelector和ImportBeanDefinitionRegistrar的实现类的回调方法的实现,对于其中真正注册bean的地方并不在这,这里只是把需要注册的bean的类放在了一个map中。
/**
*
* @param configClass 封装了bd
* @param currentSourceClass 封装了类全名
* @param importCandidates 一个集合,集合中的元素封装了import中的值
* @param checkForCircularImports 传进来的是true
*/
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
//如果是空集合就直接返回不分析
if (importCandidates.isEmpty()) {
return;
}
//判断这个bd是不是已经被解析过了
//如果是抛出异常
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
//不是就开始分析
else {
this.importStack.push(configClass);
try {
//循环遍历每一个import注解
for (SourceClass candidate : importCandidates) {
//判断注解的内容是不是ImportSelector实现类
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
//反射实现一个ImportSelector对象
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
//判断是不是设置了延迟执行,并且ImportSelector对象实现了DeferredImportSelector
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
//加入到了一个集合中
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector