springboot是以spring為基礎的,所以本文的大部分內(nèi)容還是在分析spring瑞信,只不過是在spring boot的場景下分析。關于spring boot的自動化裝配我們會在下一篇文章分析穴豫。本文分為三個部分喧伞,通過閱讀spring boot源碼和參閱了大量其他的文章,耗時兩個禮拜绩郎,才總結出來潘鲫。因為spring的源碼篇幅巨大、設計思想很多肋杖,基本是java程序員必須掌握的技能溉仑,所以無論花費多大的時間精力去分析都是值得的。
- 第一部分:基本概念:一些通用的東西
- 第二部分:bean生命周期
- 第三部分:源碼分析
本文源碼分析基于springboot版本為2.1.3状植,對應的spring版本為5.1.5
了解一二兩個部分對spring的整個源碼分析會有很大的幫助浊竟。至于源碼分析部門還是建議大家自已去debug一遍。因為我的源碼分析部分沒有辦法做到非常詳盡津畸。
Part 1 基本概念
1.1 必須知道的接口振定、類
1.1.1 Aware
- 源碼注釋
A marker superinterface indicating that a bean is eligible to be notified by the Spring container of a particular framework object through a callback-style method.
- 翻譯
一個超級接口,指示一個bean可以被spring 容器通過回調(diào)的方式通知肉拓。
比如要在Bean中獲取它自已的BeanFactory, 那自定義的Bean實現(xiàn)BeanFactoryAware接口就可以了后频,BeanFactoryAware.setBeanFactory會在bean初始化之前被容器調(diào)用
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
- 大白話
使Bean可以具備獲取容器資源的能力
1.1.2 BeanFactoryPostProcessor
- 接口聲明
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
- 源碼注釋
Allows for custom modification of an application context's bean definitions, adapting the bean property values of the context's underlying bean factory.
- 翻譯
BeanFactory的后置處理器∨荆可以在Bean創(chuàng)建之前卑惜,BeanDefinition創(chuàng)建之后,去修改BeanDefinition(甚至可以修改Bean的屬性值)驻售。但是不建議直接修改bean的值露久,修改BeanDefinition的屬性是可以的。為什么不建議在這里修改Bean的一些屬性欺栗?如果要修改那么肯定需要獲取bean毫痕,一旦執(zhí)行獲取操作,不存在就會創(chuàng)建bean迟几。但是在這個階段很多bean的PostProcessor還沒有注冊消请。那么(1)會導致bean的一些后置處理器不會執(zhí)行(比如你自已定義的)(2)會導致bean的一些屬性沒有自動注入,因為自動注入(@autowire)也是通過bean的PostProcessor完成的瘤旨。所以除非你確定你在做什么梯啤,所以不要在這里去執(zhí)行獲取bean操作。 - 大白話
任何Bean實現(xiàn)BeanFactoryPostProcessor接口存哲,會被容器掃描到因宇,postProcessBeanFactory會被調(diào)用七婴。
1.1.3 BeanPostProcessor
- 接口聲明
public interface BeanPostProcessor {
// Bean 初始化回調(diào)之前被調(diào)用
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// Bean 初始化回調(diào)后被調(diào)用
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
何為Bean的初始化回調(diào)?InitializingBean的afterPropertiesSet 和自定義的init-method
- 源碼注釋
Factory hook that allows for custom modification of new bean instances
- 翻譯
Bean的后置處理器察滑〈蚶澹可以修改bean實例。再強調(diào)一句贺辰,不要在BeanFactoryPostProcessor的實現(xiàn)里去獲取bean和修改bean
1.1.4 BeanDefinition
- 解釋
BeanDefinition是bean在spring中的描述(比如bean的有那些屬性户盯,值是什么,有那些注解等元信息)饲化,有了BeanDefinition我們就可以創(chuàng)建Bean莽鸭。注意BeanDefinition和Bean區(qū)別。特別是在我們和別人討論或者看別人的分析的時候吃靠,要清楚我們在討論的是BeanDefinition還是bean硫眨。BeanDefinition就相當于我們定義的類,bean就相當于我們實例的對象巢块。 -
BeanDefinition具體的實現(xiàn)類如下
image.png - BeanDefinition各個實現(xiàn)的具體應用場景
BeanDefinition有很多的子實現(xiàn)礁阁,不同的子實現(xiàn)應用不同的場景。網(wǎng)上有很多的總結族奢,但是我不知道是不是因為版本的問題姥闭,我debug出來的結果和他們的有些不同。比如說AnnotatedGenericBeanDefinition表示@Configuration注解注釋的類越走,但是我debug出來的結果是只要是通過.class文件掃描出來的bean棚品,哪怕是@Configuration注解的也是用的ScannedGenericBeanDefinition。所以大家注意區(qū)分弥姻,重點關注源碼上面的注釋部分(盡管很多注釋的地方南片,讀了也不知道說的什么,但有比沒有好)
- RootBeanDefinition
直接解讀官方的注釋
// 在運行時root bean表示一個merge bean(存在父子關系庭敦,所以需要合并,關于MergedBeanDefinition下面有解釋)
* A root bean definition represents the merged bean definition that backs
* a specific bean in a Spring BeanFactory at runtime.
//可以用來創(chuàng)建具有繼承關系的bean
* It might have been created
* from multiple original bean definitions that inherit from each other,
* typically registered as {@link GenericBeanDefinition GenericBeanDefinitions}.
// RootBeanDefinition在運行時是bean的一個統(tǒng)一的定義薪缆,那么本身不是用RootBeanDefinition 定義秧廉,也會創(chuàng)建一個新的RootBeanDefinition。AbstractBeanFactory 中就專門創(chuàng)建了一個對象mergedBeanDefinitions用來存放拣帽,并且和DefaultListableBeanFactory中beanDefinitionMap的大小相等疼电。
* A root bean definition is essentially the 'unified' bean definition view at runtime.
*
// RootBeanDefinition可以用來創(chuàng)建自定義的BeanDefinition
* <p>Root bean definitions may also be used for registering individual bean definitions
* in the configuration phase. However,
// 從Spring 2.5開始推薦使用GenericBeanDefinition,為什么我們下面講
* since Spring 2.5, the preferred way to register
* bean definitions programmatically is the {@link GenericBeanDefinition} class.
// GenericBeanDefinition 允許動態(tài)的定義父BeanDefinition(這里的動態(tài)不知道什么意思减拭,在源碼中沒有發(fā)現(xiàn)在上面地方使用這個動態(tài))蔽豺,不像RootBeanDefinition是硬編碼的
* GenericBeanDefinition has the advantage that it allows to dynamically define
* parent dependencies, not 'hard-coding' the role as a root bean definition.
*
- ChildBeanDefinition
可以從父BeanDefinition繼續(xù)屬性,通過構造函數(shù)或者setParentName可以設置父BeanDefinition - GenericBeanDefinition
GenericBeanDefinition是官方推薦的BeanDefinition拧粪,因為GenericBeanDefinition一個類就可以替代RootBeanDefinition和ChildBeanDefinition的修陡。主要是因為GenericBeanDefinition可以直接設置父BeanDefinition沧侥。個人感覺也沒啥。我們看下源碼中注解
/**
// 一站式商店魄鸦,可以構造參數(shù)宴杀、屬性值(MutablePropertyValues)
* GenericBeanDefinition is a one-stop shop for standard bean definition purposes.
* Like any bean definition, it allows for specifying a class plus optionally
* constructor argument values and property values. Additionally, deriving from a
* parent bean definition can be flexibly configured through the "parentName" property.
*
// 用GenericBeanDefinition注冊用戶可見的bean definitions。用戶可見的意思就是可以在后置處理器中獲取
* <p>In general, use this {@code GenericBeanDefinition} class for the purpose of
* registering user-visible bean definitions (which a post-processor might operate on,
* potentially even reconfiguring the parent name). Use {@code RootBeanDefinition} /
* {@code ChildBeanDefinition} where parent/child relationships happen to be pre-determined.
*
總的來說拾因,就是推薦使用GenericBeanDefinition
- ConfigurationClassBeanDefinition
/**特指從configuration class中創(chuàng)建的bean definition
* {@link RootBeanDefinition} marker subclass used to signify that a bean definition
* was created from a configuration class as opposed to any other configuration source.
* Used in bean overriding cases where it's necessary to determine whether the bean
* definition was created externally.
*/
一般就是指用@Bean注解的bean
- AnnotatedGenericBeanDefinition
springboot的啟動類的bean表述是用該類定義的旺罢。類中有一個重要的屬性AnnotationMetadata可以用來獲取bean的所有的注解信息 - ScannedGenericBeanDefinition
springboot是從啟動來開始來掃描bean且是通過掃描.class文件的方式掃描的,所以除了啟動類意外绢记,所有的有@Component(包括@Configuaration, @service, @Controller)注解的bean都是包裝成ScannedGenericBeanDefinition的, 但是@Bean注解的bean不是 - MergedBeanDefinition
其實spring中并沒有該類的具體定義扁达,但是源碼中又存在像getMergedBeanDefinition方法和MergedBeanDefinitionPostProcessor這個bean級別的后置處理器。其實在spring中MergedBeanDefinition對應的具體類是RootBeanDefinition蠢熄。那么什么是MergedBeanDefinition罩驻?MergedBeanDefinition又是在springboot源碼中什么時候處理的
-
什么是MergedBeanDefinition
MergedBeanDefinition表示將存在父子關系的bean的合并,也就是說你可以定義個一對存在繼承關系的bean护赊。spring會在某個時候?qū)⑵浜喜ⅲ▽⒏竍ean的屬性拷貝一份到子bean) -
MergedBeanDefinition的merge發(fā)生在那里
在執(zhí)行BeanDefinitionRegistryPostProcessor(發(fā)現(xiàn)bean惠遏,注冊BeanDefinition)之前。springboot是通過如下代碼去容器中查找BeanDefinitionRegistryPostProcessor后置處理器的
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false)
合并BeanDefinition就是在DefaultListableBeanFactory.getBeanNamesForType方法中
1.1.5 ConfigurationClassPostProcessor
用于處理啟動配置類骏啰,@SpringBootApplication中存在@Configuration注解
{@link BeanFactoryPostProcessor} used for bootstrapping processing of
{@link Configuration @Configuration} classes.
首先這是一個實現(xiàn)了BeanFactoryPostProcessor的后置處理器节吮,而且還是實現(xiàn)了BeanDefinitionRegistryPostProcessor的后置處理器。spring的bean掃描判耕、注冊透绩、自動配置等一切功能都由ConfigurationClassPostProcessor開始
1.2 Full 模式和Lite模式
此部分參考了 Spring的@Configuration配置類-Full和Lite模式,并結合了自已的源碼分析
Full 模式和Lite模式是針對spring中的bean而言的壁熄,在ConfigurationClassUtils.checkConfigurationClassCandidate方法中有關于是Full 還Lite模式的判斷
if (isFullConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (isLiteConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
1.2.1 Full模式和Lite模式的定義
官方定義為:
類上有@Configuration注解的就是Full模式帚豪。
類上沒有@Configuration注解,但是里面有@Bean方法就稱為Lite模式草丧。
透過源碼再看這個定義是不完全正確的狸臣,而應該是有如下case均認為是Lite模式的配置類:
- 類上標注有@Component注解(包含@Service、@Controller)
- 類上標注有@ComponentScan注解
- 類上標注有@Import注解
- 類上標注有@ImportResource注解
- 若類上沒有任何注解昌执,但類內(nèi)存在@Bean方法
以上case的前提均是類上沒有被標注@Configuration烛亦,在Spring 5.2之后新增了一種case也算作Lite模式:標注有@Configuration(proxyBeanMethods = false),注意:此值默認是true哦懂拾,需要顯示改為false才算是Lite模式
細心的你會發(fā)現(xiàn)煤禽,自Spring5.2(對應Spring Boot 2.2.0)開始,內(nèi)置的幾乎所有的@Configuration配置類都被修改為了@Configuration(proxyBeanMethods = false)岖赋,目的何為檬果?答:以此來降低啟動時間,為Cloud Native繼續(xù)做準備。
1.2.2 Full模式和Lite模式的不同
Full模式下:配置類會被CGLIB增強(生成代理對象)选脊,放進IoC容器內(nèi)的是代理
Lite模式下:放進IoC容器內(nèi)的是類的實例杭抠,沒有代理
代理的好處就是我們可以在方法的前后做一些其他的事情(AOP思想)
1.2.3 為什么需要Full模式和Lite模式
假設已經(jīng)存在Persion類,請思考下面兩段代碼中的persion1和persion2是不是相等的(是不是同一個對象)
@Configuration
public class MainConfiguration{
@Bean("persion1")
public Persion persion1() {
return new Persion("payne");
}
@Bean("persion2")
public Persion persion2() {
return persion1();
}
}
@Component
public class MainConfiguration{
@Bean("persion1")
public Persion persion1() {
return new Persion("payne");
}
@Bean("persion2")
public Persion persion2() {
return persion1();
}
}
在Full模型下知牌,也就是代碼片段一祈争。persion1和persion2是相等的,盡管在persion2()方法中調(diào)用了persion1()方法角寸。persion1()中每次是new 一個Persion的
在Lite模式下菩混,也就是代碼片段二,persion1和persion2是不相等的扁藕。
如果沒有代理對象沮峡,我們是做不到代碼一中的效果的。
Part 2 Bean生命周期
spring bean 的生命周期在BeanFactory接口注釋中有完整的描述亿柑。分為兩個部分邢疙,第一部分是bean可使用之前的部分,第二部分為shutdown bean factory之后的
// 第一部分
* <p>Bean factory implementations should support the standard bean lifecycle interfaces
* as far as possible. The full set of initialization methods and their standard order is:
* <ol>
* <li>BeanNameAware's {@code setBeanName}
* <li>BeanClassLoaderAware's {@code setBeanClassLoader}
* <li>BeanFactoryAware's {@code setBeanFactory}
* <li>EnvironmentAware's {@code setEnvironment}
* <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
* <li>ResourceLoaderAware's {@code setResourceLoader}
* (only applicable when running in an application context)
* <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* (only applicable when running in an application context)
* <li>MessageSourceAware's {@code setMessageSource}
* (only applicable when running in an application context)
* <li>ApplicationContextAware's {@code setApplicationContext}
* (only applicable when running in an application context)
* <li>ServletContextAware's {@code setServletContext}
* (only applicable when running in a web application context)
* <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
* <li>InitializingBean's {@code afterPropertiesSet}
* <li>a custom init-method definition
* <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
* </ol>
*
//第二部分
* <p>On shutdown of a bean factory, the following lifecycle methods apply:
* <ol>
* <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
* <li>DisposableBean's {@code destroy}
* <li>a custom destroy-method definition
* </ol>
整理如下:
第一部分
- BeanNameAware.setBeanName
- BeanClassLoaderAware.setBeanClassLoader
- BeanFactoryAware.setBeanFactory
- EnvironmentAware.setEnvironment
- EmbeddedValueResolverAware.setEmbeddedValueResolver
- ResourceLoaderAware.setResourceLoader
- ApplicationEventPublisherAware.setApplicationEventPublisher
- MessageSourceAware.setMessageSource
- ApplicationContextAware.setApplicationContext
- ServletContextAware.setServletContext
- BeanPostProcessors.postProcessBeforeInitialization
- InitializingBean.afterPropertiesSet
- a custom init-method definition
- BeanPostProcessors.postProcessAfterInitialization
以上生命周期是按發(fā)生的順序排序的望薄,最早的生命周期BeanNameAware.setBeanName也是發(fā)生在bean實例化疟游、填充屬性之后的,此時的bean已經(jīng)是一個完整的對象了痕支,已經(jīng)是可用狀態(tài)颁虐。
借用參考文獻一的圖如下:
image.png
第二部分
- DestructionAwareBeanPostProcessors.postProcessBeforeDestruction
- DisposableBean.destroy
- a custom destroy-method definition
bean更完整的生命周期
但是以上的上面周期僅僅是我們自已定義的bean能看到的生命周期,那spring 本身一些bean的生命周期是沒有包含在這里面的卧须。很久之前寫過一篇通過xml注冊bean的生命周期文章中總結過一個完整的圖另绩,在這里同樣適用,因為spring的bean生命周期是一樣的花嘶。大家也可以再看一下這篇文章前面總結的一些概念spring bean 生命周期笋籽。我們再把圖搬過來一下
這個圖第一行BeanDefinitionRegistryPostProcessor的實例化就是指的我們在1.1.5節(jié)提到的ConfigurationClassPostProcessor。重要的事情多提幾遍ConfigurationClassPostProcessor是spring boot中IOC的起點椭员。
Part 3 源碼分析
源碼分析部分车海,我會在我認為重要的地方寫上注釋,也會去掉一些我任認為不重要的地方拆撼。
目錄的編號對應注釋前面的編號
springboot的代碼篇幅比較大容劳。我們暫且分為三個大的部分
- 啟動初始化部分
- bean掃描部分
- bean的實例化部分
啟動初始化部分
3.1、SpringApplication.run方法
public ConfigurableApplicationContext run(String... args) {
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//(1)添加一些基本的類型轉(zhuǎn)換器(2)配置環(huán)境(1闸度、配置文件,2蚜印、激活了那個profile(3)占位符等(@value注解的占位符))
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
//打印springboot的banner
Banner printedBanner = printBanner(environment);
//創(chuàng)建ApplicationContent, (1)DefaultListableBeanFactory也在這里創(chuàng)建 (2) 這里有一個非常重要的BeanFactoryPostProcessor:ConfigurationClassPostProcessor在這里面注冊
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//(3)加載primarySources(其實就是我們的啟動類)莺禁,將其注冊為一個bean(bean的注冊指創(chuàng)建一個BeanDefinition,然后放到beanDefinitionMap對象中窄赋,并沒有完成實例化)
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//(4) 最復雜哟冬,關鍵的地方楼熄,下面詳細講解
refreshContext(context);
// (5)當ApplicationContent refresh 后,執(zhí)行該方法浩峡,這里是一個空的實現(xiàn)
afterRefresh(context, applicationArguments);
stopWatch.stop();
listeners.started(context);
callRunners(context, applicationArguments);
listeners.running(context);
return context;
}
3.1.4 springApplication.refreshContext詳解
springApplication.refreshContext方法實際調(diào)用的是AbstractApplicationContext.refresh()方法可岂。下面直接看該方法
public void refresh() throws BeansException, IllegalStateException {
// (1)無重要內(nèi)容,主要設置啟動時間翰灾,激活標志
prepareRefresh();
// (2)無重要內(nèi)容缕粹,獲取bean factory(實際類型為DefaultListableBeanFactory在上面已經(jīng)創(chuàng)建過了)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// (3)添加了兩個重要的BeanPostProcessor,(1)ApplicationContextAwareProcessor纸淮,bean生命周期關于Aware部分的就是通過添加該bean post processor 實現(xiàn) (2)ApplicationListenerDetector平斩,關于事件監(jiān)聽(發(fā)布-訂閱者模式)是通過該bean post processor 實現(xiàn)的(3)添加了3個bean(environment, systemProperties咽块,systemEnvironment)看名字就知道是關于系統(tǒng)一些變量的
prepareBeanFactory(beanFactory);
// (4)無具體實現(xiàn)绘面,其他content可以重寫改方法
postProcessBeanFactory(beanFactory);
// (5)調(diào)用一些已經(jīng)注冊為bean的BeanFactoryPostProcessor,還記的創(chuàng)建content時候我們提到的那個 重要的ConfigurationClassPostProcessor類嗎侈沪?
invokeBeanFactoryPostProcessors(beanFactory);
// (6)Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
//(7)國際化相關處理
initMessageSource();
//(8) 事件通知機制揭璃,發(fā)布訂閱者實現(xiàn)
initApplicationEventMulticaster();
// (9)其他的上下文比如web應用等可以實現(xiàn)改方法,用來實例化一些特殊的bean
onRefresh();
// (10)事件通知機制亭罪,注冊事件
registerListeners();
// (11)我們在invokeBeanFactoryPostProcessors中掃描到了很對的bean瘦馍,我們執(zhí)行將其BeanDefinition注冊到容器中,但是還沒有實例化皆撩,那么實例化就在finishBeanFactoryInitialization中實例化扣墩。包括BeanPostProcessor的執(zhí)行
finishBeanFactoryInitialization(beanFactory);
// (12)Last step: publish corresponding event.
finishRefresh();
}
3.2 bean的掃描部分
3.2.1 invokeBeanFactoryPostProcessors
/**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
該方法的注釋寫的很明白,實例化并且調(diào)用注冊為bean的BeanFactoryPostProcessor扛吞,這里面會調(diào)用我們在createApplicationContext方法中注冊為bean的ConfigurationClassPostProcessor對象呻惕,該對象是是一個BeanFactoryPostProcessor。試想一下spring boot是如何找到我們定義的bean的呢滥比?其他就是通過ConfigurationClassPostProcessor
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 后置處理器已經(jīng)執(zhí)行過的bean亚脆,防止執(zhí)行多次
Set<String> processedBeans = new HashSet<>();
// 將后置處理器分類,具體的見代碼下面的解釋
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//(1) 執(zhí)行invokeBeanDefinitionRegistryPostProcessors registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// 見下面解釋
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 獲取BeanDefinitionRegistryPostProcessor的bean名稱盲泛,實際上注冊為bean且類型是BeanDefinitionRegistryPostProcessor的類就是ConfigurationClassPostProcessor濒持,且只有這一個
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// ConfigurationClassPostProcessor是實現(xiàn)了PriorityOrdered接口的
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//beanFactory.getBean 當bean沒有實例化的時候,會實例化寺滚,所以ConfigurationClassPostProcessor之前只是一個BeanDefinition,在這里會實例化
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// (1)這里才是正式的ConfigurationClassPostProcessor柑营, 會將所有滿足bean條件的BeanDefinition注冊 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 獲取BeanDefinitionRegistryPostProcessors 類型的bean 并且實現(xiàn) Ordered接口
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// (1)再次執(zhí)行BeanFactoryPostProcessors, 注意如果上面已經(jīng)執(zhí)行過了,則不再執(zhí)行 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 在執(zhí)行上面后置處理器的過程中村视,會掃描到一些新的后置處理器官套,那么也要執(zhí)行
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
//(1) 執(zhí)行invokeBeanDefinitionRegistryPostProcessors invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// (2)之前注冊過一個重要的BeanFactoryPostProcessor: ConfigurationClassPostProcessor在這里會被調(diào)用,如果Bean是Full 模式的,那么cglib生成代理類放到beanDefinitionMap中
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 在掃描的過程中會發(fā)現(xiàn)新的實現(xiàn)BeanFactoryPostProcessor的bean奶赔,不如我們自已實現(xiàn)的一些后置處理器
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 實現(xiàn) PriorityOrdered的后置處理器先執(zhí)行
// 實現(xiàn)Ordered的后置處理其次, 最后是其他的后置處理器
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
//(2)執(zhí)行invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
//(2)執(zhí)行invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
//(2)執(zhí)行invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
總結
(1)方法中有三個主要的對象:
- regularPostProcessors:普通的后置處理器惋嚎,只實現(xiàn)BeanFactoryPostProcessor接口
- registryProcessors:除了實現(xiàn)BeanFactoryPostProcessor還實現(xiàn)BeanDefinitionRegistryPostProcessor的后置處理器
- currentRegistryProcessors:在容器中注冊為bean且類型是BeanDefinitionRegistryPostProcessor的后置處理器(注意并發(fā)所有的后置處理器都會注冊為bean),這里只有ConfigurationClassPostProcessor是滿足條件的
上面對象中的后置處理器都執(zhí)行完了站刑,才會執(zhí)行我們自已定義的后置處理器和我們再掃描過程中發(fā)現(xiàn)的后置處理器另伍,我們經(jīng)常使用@value("${變量名稱}")來填充屬性值就是通過在這里掃描到的PropertySourcesPlaceholderConfigurer這個后置處理器實現(xiàn)的
(2)執(zhí)行順序
- currentRegistryProcessors中實現(xiàn)PriorityOrdered的后置處理器最先執(zhí)行
- currentRegistryProcessors中實現(xiàn)Ordered的后置處理器其次
- registryProcessors中的后置處理器
- regularPostProcessors中的后置處理器最后
- 我們自已在代碼注冊的后置處理器(就是通過ConfigurationClassPostProcessor才讓容器發(fā)現(xiàn)我們自已定義的后置處理器的,所以肯定是最后執(zhí)行)
兩條原則
1. 先執(zhí)行實現(xiàn)BeanDefinitionRegistryPostProcessor的后置處理器绞旅,后執(zhí)行實現(xiàn)BeanFactoryPostProcessor的限制性(注意執(zhí)行的方法不一樣)
2. 實現(xiàn)PriorityOrdered的后置處理器先執(zhí)行摆尝,實現(xiàn)Ordered的后執(zhí)行
結合代碼來說就是BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry先執(zhí)行,BeanFactoryPostProcessor.postProcessBeanFactory后執(zhí)行玻靡。BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor實現(xiàn)類结榄,所以ConfigurationClassPostProcessor先執(zhí)行postProcessBeanDefinitionRegistry來注冊BeanDefinition,然后執(zhí)行postProcessBeanFactory將Full模式的bean class用cglib生成代理類放到beanDefinitionMap中
3.2.1.1 invokeBeanDefinitionRegistryPostProcessors
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
// 調(diào)用ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
postProcessBeanDefinitionRegistry實際處理邏輯在processConfigBeanDefinitions中
ConfigurationClassPostProcessor.processConfigBeanDefinitions處理邏輯
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
// 獲取當前content所有的BeanDefinition(沒有實例化的bean)
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//(1)關于Full模式和life模式參見文章末尾囤捻,這里主要是找出聲明了注解@Configuration或者@Component的類(注意像@Service臼朗,@Controller等存在嵌套的元注解@Component也是滿足這里的條件的)
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
// (2) 判斷該類有沒有可能是configuration 類
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 由于springboot的啟動類上是有@SpringBootApplication注解的,該注解是存在@Configuration嵌套注解的蝎土,所以啟動類肯定是滿足這個條件的configCandidates里面最起碼是存在啟動類的這個對象的
if (configCandidates.isEmpty()) {
return;
}
// 創(chuàng)建一個@Configuration class解析類
// 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());
//(4)注意這里是一個循環(huán)视哑,正常情況下,這里的candidates里面只有一個springboot啟動類誊涯,所以該循環(huán)的作用就是如果在掃描啟動類的過程又碰到新的@Configuration class那么一直掃描下去挡毅,知道找出所有的@Configuration class,掃描完了其實Bean也就掃描完了
do {
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//(5)Configuration class 中的@Bean 方法還沒有注冊BeanDefinition, 下面會注冊(掃描@Import注解時暴构,也會出現(xiàn)新的Configuration class(自動配置))
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
// 在掃描到的Configuration class中也是有@Component注解的跪呈,那么循環(huán)的掃描
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
parse的調(diào)用鏈比較長,跳過無關的方法取逾,掃描的核心邏輯在下面的方法中
3.2.1.1.4 ConfigurationClassParser.doProcessConfigurationClass
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//如果該ConfigurationClass存在成員內(nèi)部類耗绿,那么遞歸的掃描該類
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
}
// 處理@PropertySource注解
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");
}
}
// 處理@ComponentScan 注解,ComponentScan會掃描我們啟動類所在包下面所有的class文件砾隅,將所有有@Component注解的class會封裝成BeanDefinition注冊到容器中
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) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 遞歸的掃描上面掃描到的scannedBeanDefinitions误阻,如果該class上還有@PropertySource,@ComponentScan等注解就一直遞歸的處理
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());
}
}
}
}
// 處理@Import 注解, @SpringBootApplication的復合注解@EnableAutoConfiguration中存在@Import(AutoConfigurationImportSelector.class)晴埂,springboot中的自動配置就是在這里通過這個注解實現(xiàn)的
processImports(configClass, sourceClass, getImports(sourceClass), true);
// 處理 @ImportResource 注解
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 處理 @Bean注解的 方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 處理接口的默認方法
processInterfaces(configClass, sourceClass);
// 處理父類 superclass
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
總結一下究反,方法的參數(shù)ConfigurationClass就是我們的啟動的封裝類,所以掃描就是從我們的啟動類開始掃描的
(1) 方法作用
遞歸的掃描滿足條件的Bean將其封裝成BeanDefinition注冊到容器上下文中儒洛。遞歸是從ConfigurationClass開始的精耐,那么ConfigurationClass是如何定義的呢?通過如下方法判斷琅锻。
ConfigurationClassUtils.checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory)
總結一下就是:如果類上面有@Component注解就是ConfigurationClassCandidate黍氮,因為@Configuration,@Service,@Controller等注解的元注解也是包含@Component的所以有這些注解的類也是ConfigurationClassCandidate唐含。特別浅浮,如果類上沒有注解但是沫浆,存在@Bean方法注解,那么該類也是ConfigurationClassCandidate
(2)掃描循序
掃描過程中只要碰到ConfigurationClassCandidate就遞歸掃描滚秩,碰到bean就將其BeanDefinition注冊到容器中
- 成員內(nèi)部類
- @PropertySource注解
- @ComponentScan注解
- @Import注解
- @ImportResource注解
- 內(nèi)部@Bean方法
- 接口默認方法
- 父類
3.3 bean的注冊部分
bean的注冊主要實現(xiàn)在refresh方法的finishBeanFactoryInitialization
finishBeanFactoryInitialization詳解
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 設置凍結BeanDefinition的flag专执,不希望在注冊實例的時候改變bean的定義了
beanFactory.freezeConfiguration();
// (1)實例化剩下的非lazy的bean,有些bean比如自已定義的BeanPostProcessor還有容器的一些bean在之前已經(jīng)實例化過了郁油,所以這里實現(xiàn)剩下的本股,我們自已代碼中很多就是這里實例化
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
3.3.1 preInstantiateSingletons
public void preInstantiateSingletons() throws BeansException {
// beanDefinitionNames 存放所有的之前掃描到的BeanDefinition
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 遍歷所有的BeanDefinition,創(chuàng)建bean
for (String beanName : beanNames) {
// MergedBeanDefinition 之前已經(jīng)詳細說過概念桐腌,合并具有繼承關系的BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 工程bean的處理
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
// (1)獲取bean拄显,獲取不到則創(chuàng)建
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
3.3.1.1 doCreateBean
跳過不重要的調(diào)用關系直接看doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 創(chuàng)建bean實例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
// Initialize the bean instance.
Object exposedObject = bean;
try {
//填充bean屬性,@autowire字段的屬性就是在這里填充的案站,通過AutowiredAnnotationBeanPostProcessor這個后置處理器
populateBean(beanName, mbd, instanceWrapper);
// (1)初始化回調(diào)
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
3.3.1.1.1 initializeBean
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// bean生命周期與Aware相關的在這里調(diào)用
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化回調(diào)前置操作
wrappedBean =
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 初始化回調(diào)
invokeInitMethods(beanName, wrappedBean, mbd);
// 初始化回調(diào)后置操作
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean =
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}