@Import
注解常出现在@Enable
注解里面,上一篇@Enable 注解原理解析里知道@Enable
只所以能发生作用,对Spring
进行配置主要靠的就是@Import
注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
* or regular component classes to import.
*/
Class<?>[] value();
}
它的源码很简单,value为一个Class
的数组,只要这些Class是加上@Configuration
注解,或者实现了ImportSelector
或ImportBeanDefinitionRegistrar
就会自动加载了
我们简单介绍一下这三种情况
@Configuration注解我就不说了
ImportBeanDefinitionRegistrar
public interface ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}
AnnotationMetadata
就是你加上@Import
注解的地方
BeanDefinitionRegistry
然后你就可以把你需要的BeanDefinition
注册进去
ImportSelector
public interface ImportSelector {
String[] selectImports(AnnotationMetadata importingClassMetadata);
}
ImportSelector
返回一个Class的数组,这些类也可以实现ImportBeanDefinitionRegistrar
或ImportSelector
再进行配置,有点递归的赶脚,后面看他的源码实现就是递归
上面三种情况可以同时满足吗
答案是否定的
我们看一下ConfigurationClassParser#processImports
for (SourceClass candidate : importCandidates) {
// 如果import的类实现了ImportSelector
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
// 递归调用processImports
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
// 如果import的类实现了ImportBeanDefinitionRegistrar
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
// 都不满足,当做@Configuration来处理
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
ImportBeanDefinitionRegistrar
的调用细节我们后面再说.