概述
Import注解Java doc
指示要导入的一个或多个组件类,通常为@Configuration类。
提供与Spring XML中的<import/>元素等效的功能。允许导入@Configuration类、ImportSelector和ImportBeanDefinitionRegistrar实现,以及常规组件类(自4.2起;类似于AnnotationConfigApplicationContext.register(java.lang.Class<?> …))。
导入的@Configuration类中声明的@Bean定义应该使用@Autowired注入来访问。要么bean本身可以是自动装配的,要么声明bean的配置类实例可以是自动装配的。
可以在类级别和MetaAnnotation声明。
如果是XML或其他非@Configuration类需要导入@Bean定义资源,可以使用@ImportResource注解。
这个注解需要传一个Class<?>[]参数:@Configuration、ImportSelector、ImportBeanDefinitionRegistrar或者其他常规组件类。
ImportSelector接口
实现类需要根据给定的Select条件(通常是一个或多个Annotation Attribute)确定应导入哪些@Configuration类。
实现类可以实现以下Aware接口,在调用selectImports之前,将会调用它们各自的Aware逻辑:
- EnvironmentAware
- BeanFactoryAware
- BeanClassLoaderAware
- ResourceLoaderAware
或者,该类可以为单个构造函数提供一个或多个以下支持的参数类型:
- Environment
- BeanFactory
- ClassLoader
- ResourceLoader
ImportSelector实现类通常以与常规@Import注解相同的方式进行处理,但是,也可以推迟Selector导入,即直到处理完所有@Configuration类,DeferredImportSelector接口可以实现这个功能。
该接口提供一个方法:
// Select and return the names of which class(es) should be imported based on
// the AnnotationMetadata of the importing @Configuration class.
String[] selectImports(AnnotationMetadata importingClassMetadata)
DeferredImportSelector接口
继承ImportSelector接口。
ImportSelector的变体,在处理完所有@Configuration Bean之后运行。当导入为@Conditional时,这种类型的选择器可能特别有用。
实现类可以扩展Ordered接口或使用Order注释来指示相对于其他DeferredImportSelector的优先级。
getImportGroup方法需要返回一个DeferredImportSelector.Group的实现类Class对象,用于确定哪些类需要导入。
Group接口提供两个方法:
// Process the AnnotationMetadata of the importing @Configuration class
// using the specified DeferredImportSelector.
process(AnnotationMetadata metadata, DeferredImportSelector selector)
// Return the entries of which class(es) should be imported for this group.
selectImports()
ImportBeanDefinitionRegistrar接口
该接口的实现类会在处理@Configuration类时向容器注册额外的Bean定义,当需要在Bean Definition阶段进行一些操作时,这个接口的实现类就很有用。
与@Configuration和ImportSelector一起使用,可以用ImportSelector的返回值向@Import注解提供此接口的实现类。
// Register bean definitions as necessary based on the given annotation metadata
// of the importing @Configuration class.
default void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassMetadata, registry);
}
// Register bean definitions as necessary based on the given annotation metadata
// of the importing @Configuration class.
default void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
}
基本流程
ConfigurationClassPostProcessor类
在@Bean注解解析中,介绍了AnnotationConfigApplicationContext创建时会注册几个注解驱动处理器,其中就包括ConfigurationClassPostProcessor类。
他是BeanDefinitionRegistryPostProcessor实现,用于解析@Configuration类,他是按优先级排序的,因为在@Configuration类中声明的任何Bean方法都必须在任何其他BeanFactoryPostProcessor执行之前注册其对应的BeanDefinition。
他在invokeBeanFactoryPostProcessors(beanFactory)阶段被调用,通过postProcessBeanDefinitionRegistry(registry)方法解析@Configuration类。
这个过程的源码在@Bean注解解析中记录过,此处不再记录。
调用到processConfigBeanDefinitions(registry)方法,其中有一段使用ConfigurationClassParser解析@Configuration类的代码,如下:
// 1. Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
// 此处是一个do while循环
// 因为解析一遍之后,容器里面可能会有新的被注入的@Configuration Class定义,需要进一步解析
// 比如@Import注解就有可能注入新的@Configuration Class定义
do {
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// 2. Read the model and create bean definitions based on its content
this.reader.loadBeanDefinitions(configClasses);
// ...
} while (!candidates.isEmpty());
// ...
以上代码做了两件事:
- Parse @Configuration class
- 解析ConfigurationClass集注册BeanDefinition
Parse @Configuration class
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
} else if (bd instanceof AbstractBeanDefinition &&
((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
} else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanDefinitionStoreException("", ex);
}
}
// DeferredImportSelector处理
this.deferredImportSelectorHandler.process();
}
三个分支最终都会调用到processConfigurationClass方法,该方法会递归的分析一个ConfigurationClass及其父类,核心源码在以下这几行:
// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass, filter);
do {
// 分析ConfigurationClass
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
} while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
doProcessConfigurationClass方法:
-
递归解析内部类
-
解析@PropertySource注解
-
解析@ComponentScan注解
-
解析@Import注解
// Process any @Import annotations processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
-
解析@ImportResource注解
-
解析@Bean注解
-
获取父类用于递归解析
processImports方法解析@Import注解
该方法需要以下参数:
- ConfigurationClass configClass - 当前分析的@Configuration类
- SourceClass currentSourceClass - 这个参数与configClass不一样,configClass始终不变,是当前@Configuration类,而这个参数会随着递归解析父类而改变
- Collection<SourceClass> importCandidates - @Import注解导入类
- Predicate<String> exclusionFilter - 会过滤掉java.lang.annotation和org.springframework.stereotype下面的类
- boolean checkForCircularImports - 检测循环Import
代码:
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class)) {
// 这个分支支持ImportSelector
// 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) {
// 这个分支支持DeferredImportSelector
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
} else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
} else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// 这个分支支持ImportBeanDefinitionRegistrar
// 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);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
} else {
// 这个分支支持@Configuration class
// 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);
}
}
ImportSelector支持
以下的代码片段是解析ImportSelector的逻辑:
// 调用selectImports方法获取导入的组件集
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
// 这里又递归调用了processImports方法
// 所以selectImports返回的类型可以是:普通@Configuration类、ImportSelector或者ImportBeanDefinitionRegistrar
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
DeferredImportSelector支持
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
/**
* Handle the specified DeferredImportSelector.
* If deferred import selectors are being collected, this registers this instance to the list.
* If they are being processed,
* the DeferredImportSelector is also processed immediately according to its DeferredImportSelector.Group.
*/
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
if (this.deferredImportSelectors == null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
handler.register(holder);
handler.processGroupImports();
} else {
// If deferred import selectors are being collected, this registers this instance to the list.
// 等待解析了所有的@Configuration类之后再处理DeferredImportSelector
this.deferredImportSelectors.add(holder);
}
}
process核心逻辑:
public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
Predicate<String> exclusionFilter = grouping.getCandidateFilter();
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try {
processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
exclusionFilter, false);
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanDefinitionStoreException("", ex);
}
});
}
}
// getImports方法
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
return this.group.selectImports();
}
ImportBeanDefinitionRegistrar支持
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
// 实例化ImportBeanDefinitionRegistrar对象
ImportBeanDefinitionRegistrar registrar =
ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
this.environment, this.resourceLoader, this.registry);
// 添加到ConfigurationClass的importBeanDefinitionRegistrars集合
// 等待后续loadBeanDefinitions时会调用registerBeanDefinitions方法让开发者注册BeanDefinition
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
普通@Configuration类
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
// 调用processConfigurationClass方法解析@Configuration class
processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);