spring初始化源碼代碼淺析
前言
在《spring初始化源碼淺析之關(guān)鍵類和擴(kuò)展接口》中主要是關(guān)鍵類和擴(kuò)展接口的介紹,本文主要是debug代碼來看spring是如何初始化以及在分別在何時(shí)輸出上文 demo中各擴(kuò)展點(diǎn)的日志。
本文分為兩部分:《spring初始化源碼淺析之關(guān)鍵類和擴(kuò)展接口》、《spring初始化源碼淺析之代碼淺析》
1、refresh()簡(jiǎn)介
通過ClassPathXmlApplicationContext構(gòu)造方法進(jìn)入 refresh方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//容器刷新前做一些準(zhǔn)備工作
prepareRefresh();
// 創(chuàng)建DefaultListableBeanFactory對(duì)象,解析出所有BeanDefinition信息,
//注冊(cè)緩存在DefaultListableBeanFactory的beanDefinitionMap屬性中,供后面創(chuàng)建bean對(duì)象時(shí)使用
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 為beanFactory提供一些標(biāo)準(zhǔn)配置,如:類加載器、環(huán)境變量等
prepareBeanFactory(beanFactory);
try {
// 為beanFactory提供一些個(gè)性配置,通過在子上下文中復(fù)寫該方法來實(shí)現(xiàn)
postProcessBeanFactory(beanFactory);
//創(chuàng)建實(shí)現(xiàn)BeanFactoryPostProcessor的實(shí)現(xiàn)類,并執(zhí)行接口的方法。
//該方法執(zhí)行完后會(huì)輸出實(shí)例中的1-7步的日志
invokeBeanFactoryPostProcessors(beanFactory);
//創(chuàng)建BeanPostProcessor的實(shí)現(xiàn)類,并注冊(cè)到BeanFactoryPostProcessor的beanPostProcessors列表中,
//在后面創(chuàng)建普通非lazy對(duì)象時(shí)會(huì)遍歷該列表回調(diào)前置和后置方法
registerBeanPostProcessors(beanFactory);
//跟國(guó)際化消息相關(guān),沒去研究過
initMessageSource();
//初始化該上下文的事件廣播
initApplicationEventMulticaster();
//模板方法,在不同的容器刷新的時(shí)候可以自定義邏輯
onRefresh();
//創(chuàng)建ApplicationListener的實(shí)現(xiàn)類,并注冊(cè)到該上下文中
registerListeners();
//完成所有剩余的非lazy的bean的創(chuàng)建
finishBeanFactoryInitialization(beanFactory);
//上下文的創(chuàng)建完成的一些設(shè)置和緩存清理,并發(fā)布創(chuàng)建完成事件
finishRefresh();
}catch (BeansException ex) {
……
}finally {
//Reset common introspection caches in Spring's core, since we
//might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}2、關(guān)鍵代碼跟蹤
先看《spring初始化源碼淺析之關(guān)鍵類和擴(kuò)展接口》文中代碼執(zhí)行結(jié)果:

2.1、obtainFreshBeanFactory()代碼分析
首先找到beanFactory的入口方法,如下

繼續(xù)debug進(jìn)入refreshBeanFactory方法,如下

從下圖中可以看到,XmlBeanDefinitionReader為加載BeanDefinition的關(guān)鍵類,而將beanFactoy作為構(gòu)造參數(shù)主要是為了將創(chuàng)建好的BeanDefinition對(duì)象注冊(cè)到beanFactory中,后面會(huì)貼出相應(yīng)的代碼,如下

繼續(xù)斷點(diǎn)進(jìn)入XmlBeanDefinitionReader的loadBeanDefinitions方法,可見入?yún)閙ain方法中的指定配置文件的名稱,如下

斷點(diǎn)繼續(xù)走,跳過將applicationContext.xml文件解析成Document的過程,進(jìn)入registerBeanDefinitions(Document doc, Resource resource)方法,入?yún)閍pplicationContext.xml對(duì)應(yīng)的Document對(duì)象,該方法構(gòu)造一個(gè)BeanDefinitionDocumentReader對(duì)象來具體的負(fù)責(zé)從doc對(duì)象創(chuàng)建BeanDefinition對(duì)象,并注冊(cè)到beanFactory中,如下

注意 BeanDefinitionDocumentReader的registerBeanDefinitions方法一個(gè)入?yún)閄mlReaderContext對(duì)象,該對(duì)象的reader即為前面創(chuàng)建XmlBeanDefinitionReader對(duì)象。
繼續(xù)斷點(diǎn)進(jìn)入以下方法:


最后進(jìn)入DefaultListableBeanFactory的registerBeanDefinition方法,最后將創(chuàng)建好的BeanDefinition對(duì)象緩存到DefaultListableBeanFactory的一個(gè)ConcurrentHashMap中

最終將配置文件中所有的bean配置轉(zhuǎn)成BeanDefinition對(duì)象緩存起來,供后面創(chuàng)建具體的bean對(duì)象使用。
2.2、invokeBeanFactoryPostProcessors(beanFactory)代碼分析
進(jìn)入方法發(fā)現(xiàn)邏輯都交給PostProcessorRegistrationDelegate類來處理:

斷點(diǎn)一直走到下面方法,先嘗試從單利的緩存中去找,找不到再通過單例工廠類創(chuàng)建對(duì)象:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
………………
singletonObject = singletonFactory.getObject();
newSingleton = true;
…………
if (newSingleton) {
//添加到單例緩存中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
//由于緩存單例對(duì)象的 hashmap沒有hellword對(duì)象,進(jìn)入singletonFactory.getObject()方法 ,
//繼續(xù)斷點(diǎn)到 AbstractAutowireCapableBeanFactory的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對(duì)象的包裝器,beanName=hellowordService,
//該方法執(zhí)行完成后輸出第一步日志:1->HelloWorldService constructor
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();//創(chuàng)建bean對(duì)象
…………
try {
//從RootBeanDefinition 獲取屬性信息并填充到instanceWrapper對(duì)象
populateBean(beanName, mbd, instanceWrapper);
//進(jìn)入初始化bean對(duì)象的操作
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
…………
//將創(chuàng)建好的bean對(duì)象注冊(cè)到緩存起來
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
…………
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 開始調(diào)用各種ware接口的方法,會(huì)輸出2、3、4步的日志
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//執(zhí)行BeanPostProcessor的前置方法postProcessBeforeInitialization,由于
//ApplicationContextAwareProcessor實(shí)現(xiàn)該接口,該類中會(huì)執(zhí)行很多*Aware的類,而hellwordService
//實(shí)現(xiàn)ApplicationContextAware類,所在會(huì)輸出:4->ApplicationContextAware.setApplicationContext:
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//init bean對(duì)象
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//執(zhí)行BeanPostProcessor的后置方法postProcessAfterInitialization,
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
//日志輸出 2->BeanNameAware.setBeanName:helloWorldService
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
//日志輸出 3->BeanFactoryAware.setBeanFactory:
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
…………
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//日志輸出:5->InitializingBean.afterPropertiesSet
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
//執(zhí)行自定義init method方法,輸出日志 :6->init method
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
}最后回到getSingleton方法:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
……
//添加到單例緩存中
addSingleton(beanName, singletonObject);
}hellwordService對(duì)象創(chuàng)建完畢后,便執(zhí)行 下一步的invokeBeanFactoryPostProcessors方法,輸出第7步日志:
7->BeanFactoryPostProcessor.postProcessBeanFactory 將peopleService的content屬性修改為i am ok

到此為止,invokeBeanFactoryPostProcessors(beanFactory);執(zhí)行完畢
2.3、registerBeanPostProcessors(beanFactory)代碼分析
可以看到代碼和invokeBeanFactoryPostProcessors(beanFactory)的代碼模式幾乎一樣,在本方法中會(huì)創(chuàng)建所有實(shí)現(xiàn)BeanPostProcessor接口類并注冊(cè)到beanFactory中供后面對(duì)象創(chuàng)建時(shí)回調(diào),代碼不再做分析
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}2.4、registerListeners();代碼分析
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
//hellowordService便在此處注冊(cè)
getApplicationEventMulticaster().addApplicationListener(listener);
}
…………
}2.5、finishBeanFactoryInitialization(beanFactory)代碼分析
斷點(diǎn)直接進(jìn)入一下代碼:
public void preInstantiateSingletons() throws BeansException {
? ?if (logger.isTraceEnabled()) {
? ? ? logger.trace("Pre-instantiating singletons in " + this);
? ?}
? ?List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
? ?// Trigger initialization of all non-lazy singleton beans...
? ?for (String beanName : beanNames) {
? ? ? RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
? ? ? if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
? ? ? ? ?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 {
? ? ? ? ? ? //所有非lazy對(duì)象便在此處創(chuàng)建,如實(shí)例中的peopleServcie,對(duì)象創(chuàng)建過程前面已分析
? ? ? ? ? ?//peopleServcie的創(chuàng)建過程回掉beanpostProcessors的前置和后置方法,輸出日志:
? ? ? ? ? ?//8->BeanPostProcessor.postProcessBeforeInitialization->peopleService
? ? ? ? ? ?//9->BeanPostProcessor.postProcessAfterInitialization->peopleService
? ? ? ? ? ? getBean(beanName);
? ? ? ? ?}
? ? ? }
? ?}
…………
}2.4、finishRefresh()代碼分析
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
//發(fā)布ContextRefreshedEvent事件,輸入日志
//10->ApplicationListener.onApplicationEvent:
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}到此代碼分析完畢,以上只是簡(jiǎn)要的分析了初始化過程中關(guān)鍵代碼,還有很多細(xì)節(jié)大家可自己斷點(diǎn)跟蹤。
總結(jié)
到此這篇關(guān)于spring初始化源碼代碼淺析的文章就介紹到這了,更多相關(guān)spring初始化源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java編程一維數(shù)組轉(zhuǎn)換成二維數(shù)組實(shí)例代碼
這篇文章主要介紹了Java編程一維數(shù)組轉(zhuǎn)換成二維數(shù)組,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01
java實(shí)現(xiàn)簡(jiǎn)單的學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單的學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
Springboot swagger配置過程詳解(idea社區(qū)版2023.1.4+apache-maven-3
這篇文章主要介紹了Springboot-swagger配置(idea社區(qū)版2023.1.4+apache-maven-3.9.3-bin),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
詳解Spring AOP 實(shí)現(xiàn)主從讀寫分離
本篇文章主要介紹了Spring AOP 實(shí)現(xiàn)主從讀寫分離,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03
java socket長(zhǎng)連接中解決read阻塞的3個(gè)辦法
這篇文章主要介紹了java socket長(zhǎng)連接中解決read阻塞的3個(gè)辦法,本文取了折中的一個(gè)方法,并給出代碼實(shí)例,需要的朋友可以參考下2014-08-08
java在linux本地執(zhí)行shell命令的實(shí)現(xiàn)方法
本文主要介紹了java在linux本地執(zhí)行shell命令的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02

