試著把自己看原始碼對一些理解寫下來 從相對巨集觀的角度去分析整個過程碼
還是從經典的例子開始入手
private void applicationEntrance(){
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
context.getBean("account");
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent){
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
複製程式碼
要開車了,坐穩了,我們逐步進行分析
首先呼叫new FileSystemXmlApplicationContext(xml)方法,最後發現方法來到了refresh()方法,這個可以一個大名鼎鼎的方法,凡是看過或者嘗試看過spring原始碼對同學應該都對這個方法不陌生,這是一個標準的模板方法模式,由父類指定整個程式碼的執行邏輯,由子類去決定每個方法的具體實現。額,還是上程式碼吧重要的地方會寫註釋
refresh()
//applicaitonContext其實就是高配版本的Beanfactory所以很多工作還是要BeanFactory來做
//去初始化beanFactory,包括1)讀取xml,2)將xml中的bean轉為beanDefination,3)並註冊到容器中
1)obtainFreshBeanFactory()
refreshBeanFactory()
//建立BeanFactory
createBeanFactory()
loadBeanDefinitions(beanFactory)
loadBeanDefinitions(demo.xml)
1.讀取配置檔案
//將配置檔案抽象為resource
resourceLoader.load(String confLocation)
容器讀取resource
2.將配置檔案中的bean轉為spring中的格式BeanDefination並註冊到容器中
//將resource轉為document
Document doc = doLoadDocument(inputSource, resource)
//獲取xml的驗證模式
getValidationModeForResource(resource)
判斷是DTD or XSD(根據是否具有DOCTYPE)
//對xml進行解析獲取document(根據驗證模式)
this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,getValidationModeForResource(resource),isNamespaceAware());
//註冊beanDefination
registerBeanDefinitions(doc, resource)
將document轉為beanDefination
根據element進行構造
對beanDefination進行校驗
//beanName-BeanDefinition存放在Map<String, BeanDefinition> beanDefinitionMap
this.beanDefinitionMap.put(beanName, beanDefinition);
//大佬在這裡被呼叫,唯一可以插手容器啟動階段的一個bean,可以對beanDefinition進行修改
//對該型別bean會提前執行BeanFactory.getBean()
2)invokeBeanFactoryPostProcessors()
//註冊BeanPostProcessor
//真正幹活的還是beanFactory = =!
3)registerBeanPostProcessors(beanFactory)
//例項化所有單例懶載入beans
4)finishBeanFactoryInitialization(beanFactory)
遍歷 beanDefinitionMap找到單例非抽象懶載入的bean呼叫BeanFactory的getBean(beanName)
單例bean先從緩衝中讀取,如果沒有才去建立;反之直接返回
獲取depend-on到bean先去對這些bean呼叫getBean()
//以單例bean為例子
createBean()
//這裡要和postProcessBeforeInitialization區分
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation,如果這裡返回的bean非空那麼直接return(短路了)
//核心類 AbstractAutowireCapableBeanFactory
//核心方法,建立bean->填充->初始化
doCreateBean(beanName,beanDefination,args)
//建立bean的例項並用BeanWrapper包裹
1、createBeanInstance(beanName, mbd, args)
instantiateBean(beanName, mbd)
//策略模式決定如何例項化bean cglib or reflect
//反射策略居然是cglib策略的父類= =!
//對於look-up之類的功能需要cglib來支援
getInstantiationStrategy().instantiate(mbd, beanName, parent)
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw
//對BeanWrapper進行屬性填充
2、populateBean(beanName, mbd, instanceWrapper)
先去從BeanDefination中獲取property屬性放到pv中
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
程式碼來到了byName byType
//注意beanDefination中的pv僅僅表示配置的屬性,而非全屬性
以byName為例,先去遍歷已經例項化的beanWrapper中的set/is開頭的方法
再去判斷這個屬性是否是一個bean,如果是將對應的bean放到pv中稍後一起填充
InstantiationAwareBeanPostProcessor#postProcessPropertyValues
//屬性填充
applyPropertyValues(beanName, mbd, bw, pvs)
這裡有個地方之前都沒有注意過,假如beanA需要beanB的注入這時候注入對B是一份深拷貝
BeanWrapperImpl#setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv)方法對例項進行屬性填充
//初始化bean
3、initializeBean(beanName, exposedObject, mbd)
//這裡對實現各種aware結尾介面的相關屬性進行注入
invokeAwareMethods(beanName, bean)
//beanPostProcessor的前置方法
applyBeanPostProcessorsBeforeInitialization
//呼叫bean的初始化方法
invokeInitMethods(beanName, wrappedBean, mbd)
先執行InitializingBean型別的bean都afterPropertiesSet()方法
再執行<bean init-method>
//beanPostProcessor的後置方法
applyBeanPostProcessorsAfterInitialization
//註冊DisposableBean和<destroy-bean>
4、registerDisposableBeanIfNecessary
複製程式碼
AbstractAutowireCapableBeanFactory這個類是很重要的一個類