前言
根据这个名字我们不难猜的,就是导入一些信息, spring中能导入什么,无非就是导入一些类信息,进而让spring识别到转化成BeanDefinition 装入beanDefinitionMap中,这样一说好像和@Component @Service 等等没啥区别了,其实不然,这个@Import导入的类处理的比较前置,甚至处理一些BeanFactory一些信息,比如springboot中@EnableXXX 都是这么处理
接口信息
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class<?>[] value();
}
非常简单就一个属性value, 里面是方Class 信息
解析Import接口时机
源码分析
org.springframework.context.annotation.ConfigurationClassParser#processImports
org.springframework.context.annotation.ConfigurationClassParser#processImports
/**
* 处理我们的@Import注解,注意我们的@Import注解传入的参数,可能有三种类型
* 1,传入一个class类,直接解析
* 2,传入一个registrar,需要解析这个registrar
* 3,传入一个ImporterSelector,这时候会去解析ImporterSelector的实现方法中返回的数组的class
*
*/
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
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 selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
//如果为延迟导入处理则加入集合当中
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
///根据ImportSelector方法的返回值来进行递归操作
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
//获取实例对象,如果同时实现Aware接口此时触发aware中相关接口
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
//添加的一个和Importselector方式不同的map中,sprig对两种方式传入的类注册方式不同
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
// 如果当前的类既不是ImportSelector也不是ImportBeanDefinitionRegistar就进行@Configuration的解析处理
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
总结
从上面的源码中我们发现@Import 导入的信息分3类:
a)import一个普通类:@Import(A.class)
b)import一个Registrar:比如我们的aop @Import(AspectJAutoProxyRegistrar.class)
c)import一个ImportSelector:具体妙用见Spring源码之 ImportSelector
@Component,@Service,@Repository这这样注入spring和@Import 处理时机不同:
至于spring在什么时候处理的呢,我大致叙述一下,有兴趣的可以自己去研究下spring源码:
对于普通类,spring在doScan的时候,就将扫描出来的java类转换成我们的BeanDefinition,然后放入一个BeanDefinitionMap中去
对于@import的三种情况,处理就在我们的ConfigurationClassPostProcessor(该类是我们BeanDefinitionRegistryPostProcessor后置处理器的一个实现,同时这也是我们spring内部自己维护的唯一实现类(排除内部类)),具体处理import的核心代码如下,if-else 很容易可以看出spring对于我们import三种类型的处理。