『SpringBoot 源码分析』run() 方法执行流程:(4)刷新应用上下文-处理 @Import 注解
- 基于 2.2.9.RELEASE
- 问题:当方法进行了注释标记之后,springboot 又是怎么注入到容器中并创建类呢?
- 首先创建测试主程序
package com.lagou;
@SpringBootApplication
public class SpringBootMytestApplication{
public static void main(String[] args) {
SpringApplication.run(SpringBootMytestApplication.class, args);
}
}
- 创建测试 Controller
package com.lagou.controller;
@RestController
public class TestController {
@RequestMapping("/test")
public String test(){
System.out.println("源码环境构建成功...");
return "源码环境构建成功";
}
}
处理 @Import 注解
- 在上一篇当中只讲述了在 refreshContext() 时处理 @ComponentScan 的流程,这步来简单看看处理 @Import 的流程。首先断点要先跳过 com.lagou.config.MyDataSourceConfig 与 com.lagou.controller.TestController 的 parse() 处理,直到 sourceClass 为主类 com.lagou.SpringBootMytestApplication
class ConfigurationClassParser {
...
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
processMemberClasses(configClass, sourceClass, filter);
}
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
...
return null;
}
}
- 在处理前首先要获取要 import 的类,所以会先找到注解内所有的 @Import 标记的类。其中 collectImports() 会递归去找注解内所有 @Import 的信息,然后返回
class ConfigurationClassParser {
...
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
Set<SourceClass> imports = new LinkedHashSet<>();
Set<SourceClass> visited = new LinkedHashSet<>();
collectImports(sourceClass, imports, visited);
return imports;
}
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
throws IOException {
if (visited.add(sourceClass)) {
for (SourceClass annotation : sourceClass.getAnnotations()) {
String annName = annotation.getMetadata().getClassName();
if (!annName.equals(Import.class.getName())) {
collectImports(annotation, imports, visited);
}
}
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
}
}
}
- 其中,对于主类 com.lagou.SpringBootMytestApplication 所扫描的 import 类(分别是 @EnableAutoConfiguration 注解内的 AutoConfigurationImportSelector.class、AutoConfigurationPackages.Registrar.class)如下
- processImports() 只是把类注册到 IOC 容器 beanDefinitionMap 中,但还没实际进行调用。实际调用在 DeferredImportSelectorHandler 里面执行(主要是调用 AutoConfigurationImportSelector.class 的方法)
class ConfigurationClassParser {
private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();
...
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(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
this.deferredImportSelectorHandler.process();
}
}
- 接下来会获取 DeferredImportSelectorHolder 来执行 @Import 导入的类
class ConfigurationClassParser {
...
private class DeferredImportSelectorHandler {
@Nullable
private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();
...
public void process() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
deferredImports.forEach(handler::register);
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
}
}
- 在 processGroupImports() 中,会遍历其中一个与 org.springframework.boot.autoconfigure.AutoConfigurationImportSelector 相关的DeferredImportSelectorGrouping
class ConfigurationClassParser {
...
private class DeferredImportSelectorGroupingHandler {
...
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(
"Failed to process import candidates for configuration class [" +
configurationClass.getMetadata().getClassName() + "]", ex);
}
});
}
}
}
}
- 其中,groupings 属性示图如下,其中 group 属性为:org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup,而 deferredImports 属性为包含了主类 com.lagou.SpringBootMytestApplication 的ConfigurationClass,以及 org.springframework.boot.autoconfigure.AutoConfigurationImportSelector 对象
- 接下来,调用 getImports() 时,会遍历 groupings 属性中的 deferredImports 属性,然后交由对应的 group 类来处理。举例这里就是交给 org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup 来处理 org.springframework.boot.autoconfigure.AutoConfigurationImportSelector 对象的执行
class ConfigurationClassParser {
...
private static class DeferredImportSelectorGrouping {
private final DeferredImportSelector.Group group;
private final List<DeferredImportSelectorHolder> deferredImports = new ArrayList<>();
...
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
return this.group.selectImports();
}
}
}
- 接下来就走到扫描获取自动装配类的过程当中了,这在 『SpringBoot 源码分析』自动配置 这一章就讲述过了,就不在这重复描述
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
...
private static class AutoConfigurationGroup
implements DeferredImportSelector.Group, BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware {
private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();
private final Map<String, AnnotationMetadata> entries = new LinkedHashMap<>();
...
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
() -> String.format("Only %s implementations are supported, got %s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
}
}
- 接下来执行 org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup 的 selectImports(),就能看到所有的自动装配类,就导入进行来了
class ConfigurationClassParser {
...
private static class DeferredImportSelectorGrouping {
private final DeferredImportSelector.Group group;
private final List<DeferredImportSelectorHolder> deferredImports = new ArrayList<>();
...
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
return this.group.selectImports();
}
}
}
- 其中,selectImports() 返回如下
- 总结