以下都是基于spring-5.2.8,之前的版本可能有所不同
Import 是spring中的一个注解,可以用来导入需要实例化的类,把这些类加入spring容器
而且通过Import导入进来的类是可以获取到父类上面的注解的信息,当然父类必须要先加入spring管理这个注解能起作用,这个注解是作用于类,接口上面的。
@Component
@Import({DeferredImportSelectorDemo.class,SelectImportDemo.class,AwareBean.class})
public class ImportBean {
}
Improt注解使用也是很简单的,只需要在注解里面加上需要实例化的类就行了,当然Import进来的类也可以实现一些接口。
ImportSelector,ImportBeanDefinitionRegistrar两个接口是比较特殊的接口,实现这两个接口的类必须是通过Import导入的,这两个接口的方法才会被调用。
selectImports 方法 入参是导入类的信息,返回值是String数组,数组里面是需要实例化的类的完整限定名 Dome.class.getName()
public class SelectImportDome implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
MergedAnnotations annotations = importingClassMetadata.getAnnotations();
MergedAnnotation<EnableAspectJAutoProxy> eas = annotations.get(EnableAspectJAutoProxy.class);
Object proxyTargetClass = eas.getValue("proxyTargetClass").get();
//类的完整限定名,
return new String[]{Dome.class.getName()};
}
}
@Improt注解是由 ConfigurationClassPostProcessor 处理的 ,这个类实现了 BeanDefinitionRegistryPostProcessor 在spring容器初始的时候会 调用 postProcessBeanDefinitionRegistry ,postProcessBeanFactory这个两个方法
postProcessBeanDefinitionRegistry方法会收集注解,包装注册beanDefinition
这个是具体处理@Import注解的方法
具体方法代码
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
//如果没有@Import注解直接返回,不处理
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
//循环类上面的每一个@Import
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 = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
//如果是一个DeferredImportSelector类型
if (selector instanceof DeferredImportSelector) {
//比较复杂,springboot中自动配置用到了
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
//在这里调用selectImports方法,返回所有的需要import到spring容器的beanName
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
//递归处理,有可能import进来的类又有@Import注解
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, 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 =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
//加入到importBeanDefinitionRegistrars容器中,这里还没有调用registerBeanDefinitions
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
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), 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();
}
}
}
1. Import 引入没有实现ImportSelector,ImportBeanDefinitionRegistrar接口的类会直接解析这个类
2. 1).如果是实现了ImportSelector 接口的类 就会反射实例化,然后调用selectImports方法
2).如果是实现了DeferredImportSelector 接口,会调到 DeferredImportSelectorGrouping里面的selectImports方法
其实获取方式还是ImportSelector 的selectImports
DeferredImportSelectorGrouping 也可以是自己实现的
如果没有自己实现就是走默认的
3. 实现了ImportBeanDefinitionRegistrar 接口的,会先加入importBeanDefinitionRegistrars map里面,然后处理