前言
實(shí)際上我所有的博客都是原來對原來印象筆記里筆記內(nèi)容的加工,關(guān)于Spring源碼自己已經(jīng)解析了很多遍,但是時間長總是忘記,寫一篇博客權(quán)當(dāng)加強(qiáng)記憶,也算再次學(xué)習(xí)下大師們的設(shè)計思想,思考方式。本次源碼解析對最底層的如怎么讀取xml文件等不做詳細(xì)解釋,只分析關(guān)鍵步驟和思想。
1、Spring整體架構(gòu)

Spring由很多模塊組成,我們不可能挨個模塊去看源碼去分析,看源碼本身就是一件及其枯燥乏味的事情。言簡意賅,咱們Spring源碼解析系列只挑干貨,即Core Container模塊的IOC依賴注入,AOP模塊的面向切面編程,DataAccess模塊的Trasactions事務(wù)原理和web模塊的mvc原理部分。而且分析也盡量偏向重要步驟和思想,而不是干巴巴的啃源碼。
源碼分析思路:
首先:確定IOC容器做了什么,其實(shí)主要是加載和管理bean
然后:找到做這些事情的所有頂層接口
再次:找頂層接口的干不同事情的子類、分析這些子類是做什么的
最后:挑最富有內(nèi)涵的接口分析其原理和思想,學(xué)習(xí)他們的設(shè)計思路
2、IOC容器
2.1、IOC的概念
IOC即依賴注入、控制反轉(zhuǎn),兩個概念都一樣,即把創(chuàng)建Java對象和維持對象的依賴關(guān)系的活兒交給Spring來做,把對對象的控制權(quán)交給Spring、讓對象減少耦合。我們這里把IOC叫做容器,即容納Java Bean的容器。IOC容器里面所有能提供服務(wù)的對象都叫Bean,至于怎么配置Bean這里就不過多贅述了,如果你不知道通過xml和注解配置bean那么你不應(yīng)該來看源碼。
2.2、bean的幾種形態(tài)
IOC里最重要的概念就是Bean,所有的接口都圍繞Bean確立,在真正分析之前我們先看看Bean的幾種形態(tài)。
- 形態(tài)一:xml或者注解標(biāo)注的概念態(tài),此時bean只是一個由類和一些描述文件定義的概念狀態(tài),比如:
<bean id="schedulerFactoryBean"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory" ref="jobFactory"></property>
</bean>
- 形態(tài)二:內(nèi)存中的定義態(tài),此時Bean被加載到內(nèi)存中,但還處在BeanDefinition這種定義狀態(tài),這種狀態(tài)實(shí)際上是bean創(chuàng)建的模板。
- 形態(tài)三:純凈態(tài),此時的Bean只是被Bean工廠創(chuàng)建成了對象,但是并沒有給bean的每個屬性賦值,此時各屬性還處于0 null false等這種初始狀態(tài),想想無參構(gòu)造函數(shù)創(chuàng)建的對象。
- 形態(tài)四:成熟態(tài),純凈的Bean的屬性被賦予真實(shí)有效的值,此時的Bean就是我們最終要使用的狀態(tài),已經(jīng)可以提供正常服務(wù)了。
2.3、bean相關(guān)重要接口
了解了Bean的幾個狀態(tài)后我們至少能想到幾個重要的接口。
- 接口一:Resource接口,能把xml等文件讀取到內(nèi)存中,并能夠獲取到xml文件的詳細(xì)信息。
- 接口二:Document接口,用于xml文件解析到內(nèi)存,類似于js里的dom解析。
- 接口三:BeanDefinitionReader接口,用于解析xml和加載Bean成為BeanDefinition
- 接口四:BeanDefinition接口,bean的抽象定義,如是否單例,是否是懶加載,有哪些重要屬性等等。
- 接口五:BeanFactory,Spring里面的重要模式-工廠模式,用于創(chuàng)建真正意義上的bean類。
- 接口六:ApplicationContext,應(yīng)用程序上下文,我一般都把上下文理解成容器,這個容器就是bean真正運(yùn)行的容器,spring機(jī)器也由此啟動。
2.4、bean創(chuàng)建步驟
2.4.1、創(chuàng)建步驟
上面我們了解了Bean的狀態(tài)和幾個處理Bean的工具,接著我們就看Bean是怎么從概念態(tài)變成可用的成熟態(tài)的。此處我們先以xml配置的bean為例子。
- 步驟一:資源以統(tǒng)一資源接口Resource加載入內(nèi)存,即利用Resource接口及其子類把xml加載到內(nèi)存中。(形態(tài)一)
- 步驟二:把Resource處理成Document,然后根據(jù)Dom接口處理Element節(jié)點(diǎn)即可,然后校驗,校驗過程根據(jù)DTD和XSD也就是ApplicationContext頭部的配置進(jìn)行xml格式校驗
- 步驟三:解析,解析過程包括bean的id,property以及其他方面的配置,把資源中的bean和其他標(biāo)簽(是否懶加載,是否單例等)解析成BeanDefinition格式(形態(tài)二)
- 步驟四:注冊、就是放到全局的Map中,不過注冊之前做了重名校驗,注冊的方式有別名和bean名兩種
- 步驟五:解析注冊完成之后通知監(jiān)聽器,這里只為后期擴(kuò)展用,程序員可以實(shí)現(xiàn)相關(guān)監(jiān)聽器方法對這個事件進(jìn)行處理
-
步驟六:加載,加載步驟:注意:此時加載的Bean還沒有被裝載數(shù)據(jù),還處于(形態(tài)三)純凈態(tài)
(1):轉(zhuǎn)換對應(yīng)的beanname,也就是獲取最終的beanname,別名轉(zhuǎn)換,去掉無效標(biāo)識符等
(2):嘗試從緩存中加載單例
(3):Bean的實(shí)例化
(4):原型模式的依賴檢查
(5):檢測ParentBeanFactory,如果當(dāng)前檢測到的xml文件中不包含BeanName,就去父Factory中獲取
(6):將存儲XML配置文件的GernericBeanDefinition轉(zhuǎn)換為RootBeanDefinition
(7):尋找依賴,先加載依賴的Bean
(8):針對不同的scope進(jìn)行bean的創(chuàng)建singleton,request等
(9):類型轉(zhuǎn)換 - 步驟七:步驟六弄完bean就是成熟態(tài)了(形態(tài)四)
2.4.2、方法調(diào)用鏈:
為了更好的閱讀源碼,此處先給出方法調(diào)用鏈

2.5、源碼解讀
在開始閱讀源碼之前我們先來看看重要接口的繼承體系(圖片來源于網(wǎng)絡(luò),侵刪)
-
A:Resource接口繼承體系
Resource接口UML圖
這個繼承體系里有很多接口,但我們常用的接口是圖中的藍(lán)色部分,其中每個類都對應(yīng)一種資源加載方式,比如URLResource可以從網(wǎng)絡(luò)獲取ApplicationContext.xml文件,F(xiàn)ileSystemResource可以從本地文件系統(tǒng)獲取xml。
-
B:BeanDefinitionReader接口繼承體系
BeanDefinitionReader接口繼承體系
這個體系就比較清楚了,XmlBeanDefinitionReader可以把xml文件中的bean加載到內(nèi)存中,并可以處理Document文件。
-
C:BeanDefinition接口繼承體系
BeanDefinition接口繼承體系
直接關(guān)注RootBeanDefinition,該類利用其每個父類接口的技能來包裝Bean的定義。比如定義xml的bean,還可以定義注解的bean。
-
D:BeanFactory接口繼承體系
BeanFactory接口繼承體系
BeanFactory接口里定義了多個BeanFactory,本質(zhì)上是利用了設(shè)計模式基本原則里面的單一職責(zé)原則與接口隔離原則,簡單來說就是每個接口都只干好自己的一灘事兒。比如:ListableBeanFactory可以枚舉所有的BeanDefinition、AutowireCapableBeanFactory定義了各種裝配規(guī)則,可以自動裝配Bean、ConfigurableBeanFactory可配置的BeanFactory。他們的子類DefaultListableBeanFactory可以用調(diào)用每個接口的方法去應(yīng)對不同的環(huán)境。就像郭靖有江南七怪七個老師,每個老師都有不同技能,所以郭靖可以對不同的環(huán)境使用不同老師的技能。
-
E:ApplicationContext接口繼承體系
ApplicationContext繼承體系
這個繼承體系看起來復(fù)雜,但實(shí)際上許多類本質(zhì)上是不同應(yīng)用環(huán)境下的不同容器而已,比如WebApplication是應(yīng)用于web應(yīng)用中的Ioc容器、ClassPathXmlApplicationContext可以以項目中的.xml文件的配置創(chuàng)建一個IOC容器、FileSystemXMLApplicationContext可以根據(jù)磁盤的絕對路徑獲取.xml文件配置一個IOC容器。
源碼解讀開始(以ClassPathXmlApplicationContext為例)
step1:首先創(chuàng)建并初始化一個ClassPathXml的IOC容器
public class HelloProgram {
public static void main(String[] args) {
//創(chuàng)建IOC容器
ApplicationContext context =new ClassPathXmlApplicationContext("beans.xml");
HelloWorldService service =(HelloWorldService) context.getBean("helloWorldService");
HelloWorld hw= service.getHelloWorld();
hw.sayHello();
}
}
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
//父容器被設(shè)置為Null
super(parent);
//存儲了xml的位置,以便后續(xù)獲取
setConfigLocations(configLocations);
if (refresh) {
//常規(guī)操作,初始化容器,如果之前存在就銷毀,不存在就創(chuàng)建
refresh();
}
}
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 預(yù)初始化,設(shè)置容器的啟動時間、激活標(biāo)志,初始化和驗證一些預(yù)定義的屬性(有的話)
prepareRefresh();
// 初始化BeanFactory,存在則銷毀,不存在則創(chuàng)建一個
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 對即將在IOC容器里使用的BeanFactory做一些配置,比如設(shè)置類加載器,設(shè)置回調(diào)方法等
prepareBeanFactory(beanFactory);
try {
// BeanFactory構(gòu)建完成之后事件,這個方法沒有實(shí)現(xiàn),我們可以實(shí)現(xiàn)一個。
postProcessBeanFactory(beanFactory);
// I執(zhí)行上面的事件
invokeBeanFactoryPostProcessors(beanFactory);
// 在創(chuàng)建Bean過程中注冊攔截器,這些個攔截器會在bean成為真正的成熟bean(applicationContext管理的bean)之前調(diào)用
registerBeanPostProcessors(beanFactory);
// 初始化信息源,信息源bean可以國際化的讀取properties文件
initMessageSource();
// 初始化事件廣播器,對于他內(nèi)部的監(jiān)聽者applicationListeners,每次事件到來都會一一獲取通知(這里使用了觀察者模式)
initApplicationEventMulticaster();
// 模板方法模式,埋了一個鉤子,那些想要實(shí)現(xiàn)特殊實(shí)例化bean的類可以重寫這個方法以實(shí)現(xiàn)自己的定制化初始化方案
onRefresh();
// 給事件廣播器注冊一些監(jiān)聽器(觀察者模式)
registerListeners();
// 完成BeanFacotry的初始化,初始化所有剩余的單例Bean
finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期事件處理器,并發(fā)布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
obtainFreshBeanFactory方法調(diào)用鏈
該方法為BeanFactory準(zhǔn)備創(chuàng)建Bean的原材料,即BeanDefinition,準(zhǔn)備好之后放到一個ConcurrentHashMap里面,key為beanName,value為BeanDefinition
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
protected final void refreshBeanFactory() throws BeansException {
//如果已經(jīng)存在BeanFactory那么就銷毀
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//創(chuàng)建一個默認(rèn)的BeanFactory,即全功能的那個郭靖!
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//配置beanFactory的一些定制化屬性,如是否允許循環(huán)依賴,是否支持definition重寫
customizeBeanFactory(beanFactory);
//這步就關(guān)鍵了,載入BeanDefinations,給BeanFactory工廠提供創(chuàng)建bean的原材料!
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 為當(dāng)前工廠創(chuàng)建一個BeanDefinition讀取器!
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 根據(jù)Contextn的資源對該讀取器進(jìn)行配置,得告訴他去哪讀啊,怎么讀?。? beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 這里可以設(shè)置一個定制化的Reader
initBeanDefinitionReader(beanDefinitionReader);
//此處調(diào)用了重載的方法,把已經(jīng)裝飾好的能用的BeanDefinitionReader讀取器當(dāng)參數(shù)傳了進(jìn)去
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//這里的reader已經(jīng)可以正常干活兒了,首先獲取bean定義資源
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
//顯然這個configRuations我們之前給傳了一個路徑"bean.xml",所以執(zhí)行這個重載方法
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int counter = 0;
for (String location : locations) {
counter += loadBeanDefinitions(location,null);
}
return counter;
}
尼瑪,套路好深,一個loadBeanDefinition搞這么多重載方法,擦得,總算到底了
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources);
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}
忽略我上面說的到底了,尼瑪?。。?!到這應(yīng)該算是到底了吧,這里調(diào)用的是XMLBeanDefinitionReader中的loadBeanDefinitions方法,里邊用IO流來讀取文件
//該方法從我們指定的路徑里獲取xml的bean!?。?public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
好吧,我們接著看下面的載入
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//此處把xml文件通過IO流讀入內(nèi)存并處理成Document類型,后續(xù)就可以通過dom操作了
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}catch(各種catch){
..........
}
}
@SuppressWarnings("deprecation")
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//創(chuàng)建一個解析Document的BeanDefinitionReader
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();
//利用DocumentReader注冊BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root) {
//實(shí)際上這里的root代表的是<beans>標(biāo)簽
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
return;
}
}
}
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
下面的方法利用迭代器迭代的把<beans>標(biāo)簽里的元素處理成內(nèi)存中的BeanDefinition
//真正解析bean標(biāo)簽的方法
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
下面的方法會創(chuàng)建一個BeanDefinitionHolder持有BeanDefinition及名字,別名數(shù)組
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//持有beanName,BeanDefinition和Bean的別名
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 把beanName-BeanDefinition鍵值對放到private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);里面
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// 發(fā)送注冊成功信號,告知容器已經(jīng)注冊好了所有Bean成BeanDefinition了
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
下面這個方法是最終解析xml成BeanDefinition!??!
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
//獲取BeanID
String id = ele.getAttribute(ID_ATTRIBUTE);
//獲取Bean的名字
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//獲取bean的所有別名
List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
//如果bean沒有名字其ID就是他的名字
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
//返回BeanDefinationHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
Ok以上代碼都執(zhí)行完BeanFactory的原材料算是準(zhǔn)備好了,BeanFactory可以拿著這些原材料制作Bean了
prepareBeanFactory方法解析:
該方法為BeanFactory工廠設(shè)置類加載器、bean創(chuàng)建監(jiān)聽器、初始化一些IOC容器自帶的必須要初始化的Bean
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
finishBeanFactoryInitialization(beanFactory)方法分析
該方法對那些非懶加載(spring默認(rèn))的Bean進(jìn)行預(yù)實(shí)例化
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
//對配置lazy-init屬性Bean的預(yù)實(shí)例化
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
synchronized (this.beanDefinitionMap) {
for (String beanName : this.beanDefinitionNames) {
//獲取指定名稱的Bean定義
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//bean定義為非抽象,單例模式,非懶加載
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//如果指定名稱的bean是創(chuàng)建容器的Bean
if (isFactoryBean(beanName)) {
//FACTORY_BEAN_PREFIX=”&”,當(dāng)Bean名稱前面加”&”符號 時,獲取的是產(chǎn)生容器對象本身,而不是容器產(chǎn)生的Bean.
//調(diào)用getBean方法,觸發(fā)容器對Bean實(shí)例化和依賴注入過程
final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
//標(biāo)識是否需要預(yù)實(shí)例化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
//一個匿名內(nèi)部類
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit();
}
if (isEagerInit) {
//調(diào)用getBean方法,觸發(fā)容器對Bean實(shí)例化和依賴注入過程
getBean(beanName);
}
}
else {
//調(diào)用getBean方法,觸發(fā)容器對Bean實(shí)例化和依賴注入過程
getBean(beanName);
}
}
}
}
}
下面這老長代碼我看著都害怕,這個方法是真正創(chuàng)建預(yù)實(shí)例化的Bean的方法,如果你嫌棄太長了,知道這句話也就差不多夠了。這個bean是純凈態(tài)無污染的bean哦。我們關(guān)注下面方法里的單例模式的bean的創(chuàng)建,和原型模式的bean的創(chuàng)建,直接看關(guān)鍵代碼(有注釋的)
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args,boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}
}
//
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type [" +
ClassUtils.getQualifiedName(requiredType) + "]", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
為了上面的代碼更容易觀察,我們把單例模式bean創(chuàng)建過程提取出來,下面方法的createBean就是真正創(chuàng)建Bean的地方
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
//真正創(chuàng)建Bean的地方,要把Bean和BeaNDefination信息傳給這個方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
下面的代碼就是真正執(zhí)行BeanDefination到Bean實(shí)例化的代碼,其中populateBean就是依賴注入發(fā)生的地方!?。。?/p>
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
/**根據(jù)配置的Class信息創(chuàng)建一個實(shí)例包裹器,包裹器里包裹著一個實(shí)例化的bean,但此bean并沒有被賦值**/
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//獲取到這個沒有給屬性賦值的純凈Bean
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
//如果bean涉及到了循環(huán)引用,而且是單例的,而且是在創(chuàng)建過程中,則允許該bean提前曝光,我們下一章會講解Spring中的循環(huán)引用問題
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
----------打印日志------------
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// 這里把剛剛創(chuàng)建好的bean進(jìn)行裝配,即使bean狀態(tài)變成成熟態(tài)!??!
Object exposedObject = bean;
try {
//使Bean變成成熟態(tài)的真正方法,即依賴注入的真正發(fā)生地!?。。?!
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//對bean進(jìn)行后置處理器處理
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
-----------捕獲異常-------
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
----------------拋出異常-------------
}
}
}
}
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
-------------捕獲異常-----------------
return exposedObject;
}
總結(jié)
經(jīng)過以上過程,Spring已經(jīng)啟動了一個全新的IOC容器,并把xml里配置的Bean從概念態(tài)轉(zhuǎn)變?yōu)檎嬲捎玫某墒鞈B(tài)并放到IOC容器里來管理了。我們可以通過getBean(“beanName”)來獲取Bean的成熟態(tài)實(shí)例!




