SpringBoot的自动装配是拆箱即用的基础,也是微服务化的前提。其实它并不那么神秘,我在这之前已经写过最基本的实现了,大家可以参考这篇文章。这次主要的议题是,来看看它是怎么样实现的,我们透过源代码来把握自动装配的来龙去脉。
我们在编写SpringBoot项目时,@SpringBootApplication
是最常见的注解了,我们可以看一下源代码:
这里面包含了@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan,此处@ComponentScan由于没有指定扫描包,因此它默认扫描的是与该类同级的类或者同级包下的所有类,另外@SpringBootConfiguration,通过源码得知它是一个@Configuration:
由此我们可以推断出@SpringBootApplication等同于@Configuration @ComponentScan @EnableAutoConfiguration。更多相关内容:SpringBoot内容聚合
一旦加上此注解,那么将会开启自动装配功能,简单点讲,Spring会试图在你的classpath下找到所有配置的Bean然后进行装配。当然装配Bean时,会根据若干个(Conditional)定制规则来进行初始化。我们看一下它的源码:
虽然根据文档注释的说明它指点我们去看EnableAutoConfigurationImportSelector。但是该类在SpringBoot1.5.X版本已经过时了,因此我们看一下它的父类AutoConfigurationImportSelector:
首先该类实现了DeferredImportSelector接口,这个接口继承了ImportSelector:
该接口主要是为了导入@Configuration的配置项,而DeferredImportSelector是延期导入,当所有的@Configuration
都处理过后才会执行。更多相关内容:SpringBoot内容聚合
回过头来我们看一下AutoConfigurationImportSelector的selectImport方法:
该方法刚开始会先判断是否进行自动装配,而后会从META-INF/spring-autoconfigure-metadata.properties
读取元数据与元数据的相关属性,紧接着会调用getCandidateConfigurations方法:
在这里又遇到我们的老熟人了SpringFactoryiesLoader
, 它会读取META-INF/spring.factories
下的EnableAutoConfiguration的配置,紧接着在进行排除与过滤,进而得到需要装配的类。最后让所有配置在META-INF/spring.factories
下的AutoConfigurationImportListener执行AutoConfigurationImportEvent事件,代码如下:
在前面的环节里只是最终要确定哪些类需要被装配,在SpringBoot时何时处理这些自动装配的类呢?下面我们简要的分析一下:
这个方法老生常谈了其中请大家关注一下这个方法:
在这里是处理BeanFactoryPostProcessor的,那么我们在来看一下这个接口BeanDefinitionRegistryPostProcessor:
该接口继承了BeanFactoryPostProcessor。更多相关内容:SpringBoot内容聚合
该类主要处理@Configuration
注解的,它实现了BeanDefinitionRegistryPostProcessor, 那么也间接实现了BeanFactoryPostProcessor,关键代码如下:
其实这里注释已经很清楚了,我们可以清楚的看到解析每一个@ConfigurationClass
的关键类是:ConfigurationClassParser,那么我们继续看一看这个类的parse方法:
在这里大家留意一下最后一句processDeferredImportSelectors方法,在这里将会对DeferredImportSelector进行处理,这样我们就和AutoConfigurationSelectImporter结合到一起了:
请大家关注这句代码:String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
在这里deferredImport的类型为DeferredImportSelectorHolder:
在这个内部类里持有了一个DeferredImportSelector的引用,至此将会执行自动装配的所有操作
1)自动装配还是利用了SpringFactoriesLoader来加载META-INF/spring.factoires
文件里所有配置的EnableAutoConfgruation,它会经过exclude和filter等操作,最终确定要装配的类
2) 处理@Configuration
的核心还是ConfigurationClassPostProcessor,这个类实现了BeanFactoryPostProcessor, 因此当AbstractApplicationContext执行refresh方法里的invokeBeanFactoryPostProcessors(beanFactory)
方法时会执行自动装配