『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() 返回如下
总结