之前基本理清了ClassPathXmlApplicationContext的繼承層次,但一些重點(diǎn)方法和一些重要對(duì)象并未觸及,本文繼續(xù)調(diào)試和閱讀spring源碼,希望通過(guò)此次學(xué)習(xí)可以搞明白bean的加載和生成機(jī)制。調(diào)試的Main方法如下殴泰,很簡(jiǎn)單,實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的Transaction對(duì)象叫挟,使用ClassPathXmlApplicationContext獲取transaction對(duì)象艰匙,調(diào)用對(duì)象的transaction方法。
import com.thoughtworks.Transaction;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("Application-context.xml");
Transaction transaction = (Transaction)context.getBean("transaction");
transaction.transaction();
}
}
下面是Transaction對(duì)象定義抹恳,其中stMapper用到了mybatis员凝,mybatis是比較流行的orm框架,之前也沒(méi)使用過(guò)奋献,由于項(xiàng)目中使用健霹,模仿著寫(xiě)了一個(gè)旺上,如果可以的話,順便將mybatis與spring的整合代碼一起看了糖埋。trasaction方法上我加上了@Transactional注解宣吱,這個(gè)注解實(shí)現(xiàn)從spring框架中支持了數(shù)據(jù)庫(kù)事務(wù),好處在于讓程序員避免了在每次提交事務(wù)sql時(shí)寫(xiě)那些模板代碼瞳别,通過(guò)與mybatis的整合征候,針對(duì)數(shù)據(jù)庫(kù)的操作看起來(lái)會(huì)相當(dāng)干凈,僅僅加上一個(gè)注解祟敛,就可以輕松實(shí)現(xiàn)對(duì)事物的控制疤坝。這里加上@Transactional注解,是想了解下spring的實(shí)現(xiàn)機(jī)制馆铁,之前看了一點(diǎn)這塊的代碼跑揉,了解到spring的事務(wù)本質(zhì)實(shí)際上還是AOP的方式實(shí)現(xiàn)(Spring AOP通過(guò)動(dòng)態(tài)代理的方式實(shí)現(xiàn),動(dòng)態(tài)代理本質(zhì)就是動(dòng)態(tài)生成繼承接口的類(lèi)或者繼承父類(lèi)的子類(lèi)埠巨,最終在動(dòng)態(tài)生成的代理類(lèi)中對(duì)用戶方法進(jìn)行攔截)历谍,spring實(shí)現(xiàn)了兩種動(dòng)態(tài)代理:jdk和cglib的,區(qū)別在于:jdk使用java自帶的動(dòng)態(tài)代理功能實(shí)現(xiàn)辣垒,但是只能支持代理繼承于接口的具體類(lèi)望侈;cglib是為了能支持代理非繼承接口的具體類(lèi)(final類(lèi)無(wú)法支持,因?yàn)橥ㄟ^(guò)繼承父類(lèi)實(shí)現(xiàn))乍构,使用了直接生成字節(jié)碼的方式返回class類(lèi)型(據(jù)介紹還比較屌甜无,想了解java字節(jié)碼實(shí)現(xiàn)的,可以看看這塊的源碼哥遮,不夠估計(jì)是native方法,那就得去看jvm虛擬機(jī)c語(yǔ)言源碼了)陵究。關(guān)于動(dòng)態(tài)代理在Spring AOP的實(shí)現(xiàn)方式眠饮,后續(xù)會(huì)單列一章詳細(xì)分析,此處僅簡(jiǎn)單敘述铜邮。
package com.thoughtworks;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;
@Component
public class Transaction {
@Autowired
private StMapper stMapper;
@Transactional
public void transaction() {
System.out.println(stMapper.getStockCardId(119, 572));
System.out.println(stMapper.getStockCardId(1, 1));
System.out.println(stMapper.getCMMEntryHead());
}
}
下面是StMapping的實(shí)現(xiàn)仪召,該部分是mybatis跟spring整合的代碼,雖然還沒(méi)來(lái)得及細(xì)看源碼松蒜,但是即使是猜扔茅,大概能想到mybatis也只能靠實(shí)現(xiàn)spring的某些插件類(lèi),最終注冊(cè)到spring當(dāng)中去實(shí)現(xiàn)mybatis的orm功能秸苗。如果本文篇幅夠的話召娜,可以把mybatis和spring的整合部分一起看了,不夠的話后面再單列一章惊楼。
package com.thoughtworks;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface StMapper {
@Select("select * from tmp where a = #{a}")
List<Integer> getStudent(@Param("a") int a);
@Select("select id from stock_cards where facilityid = ${facilityid} and productid = ${productid}")
Integer getStockCardId(@Param("facilityid") Integer facilityid, @Param("productid") Integer productid);
@Select("SELECT * FROM cmm_entries limit 1")
CMMEntry getCMMEntryHead();
}
ApplicationContext的xml配置玖瘸,數(shù)據(jù)庫(kù)密碼我寫(xiě)在default.properties中秸讹,由于涉及項(xiàng)目信息安全,配置文件就不放置了雅倒,配置文件就是簡(jiǎn)單key=value,每行一對(duì)配置璃诀,spring會(huì)自己去加載配置,然后替換配置中的占位符(比如${openlmis.jdbc.password})蔑匣,這塊我們也會(huì)在后面的源碼中看到spring是如何替換這些占位符的劣欢。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
<context:annotation-config/>
<context:spring-configured/>
<tx:annotation-driven transaction-manager="openLmisTransactionManager"/>
<bean id="openLmisTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="openlmisDataSource"/>
</property>
</bean>
<context:property-placeholder location="default.properties"/>
<bean id="openlmisDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${openlmis.jdbc.url}"/>
<property name="user" value="${openlmis.jdbc.username}"/>
<property name="password" value="${openlmis.jdbc.password}"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="openlmisDataSource"/>
<!--property name="typeHandlersPackage" value="org.openlmis.core.repository.typehandler"/-->
</bean>
<bean id="myBatisMapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.thoughtworks"/>
<property name="annotationClass" value="org.springframework.stereotype.Repository"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<bean id="transaction"
class="com.thoughtworks.Transaction">
<!-- 在這里寫(xiě)額外的bean的配置和相關(guān)引用 -->
</bean>
</beans>
首先,我們從上下文的初始化開(kāi)始裁良,傳入配置文件名稱凿将,該配置文件路徑放在工程的resource目錄下(default.properties也放在resource下面):
ApplicationContext context = new ClassPathXmlApplicationContext("Application-context.xml");
ClassPathXmlApplicationContext首先調(diào)用自己的構(gòu)造函數(shù),將配置文件名稱傳入趴久,隨后繼續(xù)內(nèi)部調(diào)用另外一個(gè)參數(shù)更多的構(gòu)造函數(shù)丸相,我們這里parent為null,之前看到彼棍,ApplicationContext是具有層次性的灭忠,多個(gè)ApplicationContext可以構(gòu)造層次關(guān)系。隨后調(diào)用了最重要的方法refresh方法座硕。
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
refresh方法弛作,該方法在AbstractApplicationContext中實(shí)現(xiàn)。synchronized (this.startupShutdownMonitor) 用于保證bean刷新的完整性华匾。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
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;
}
}
}
Bean加載流程解析
prepareRefresh
prepareRefresh負(fù)責(zé)刷新前的準(zhǔn)備工作映琳,包括環(huán)境信息、配置路徑信息的初始化蜘拉。
obtainFreshBeanFactory
隨后萨西,會(huì)初始化一個(gè)重要對(duì)象--beanFactory,該beanFactory對(duì)象為ConfigurableListableBeanFactory類(lèi)型旭旭。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
查看obtainFreshBeanFactory方法谎脯,調(diào)用了AbstractApplicationContext中的兩個(gè)抽象方法refreshBeanFactory和getBeanFactory,在AbstractApplicationContext中持寄,多個(gè)涉及beanFactory的方法都是抽象方法源梭,該beanFactory對(duì)象為ConfigurableListableBeanFactory。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
AbstractApplicationContext的直接子類(lèi)AbstractRefreshableApplicationContext實(shí)現(xiàn)了refreshBeanFactory和getBeanFactory的方法稍味,getBeanFactory里面直接獲取的beanFactory對(duì)象废麻,而負(fù)責(zé)beanFactory對(duì)象初始化方法的實(shí)際上是refreshBeanFactory,在不涉及重建beanFactory的場(chǎng)景中模庐,refreshBeanFactory方法不會(huì)觸發(fā)if分支烛愧。其中createBeanFactory負(fù)責(zé)beanFactory的創(chuàng)建,該beanFactory類(lèi)型為DefaultListableBeanFactory,這個(gè)類(lèi)負(fù)責(zé)代理所有涉及beanFactory的動(dòng)作屑彻,所以這個(gè)類(lèi)相當(dāng)重要验庙。
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return this.beanFactory;
}
}
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
下圖為DefaultListableBeanFactory的繼承層次:
之前已經(jīng)介紹過(guò)的接口不再重復(fù)介紹,只介紹新遇到的接口和類(lèi)型社牲。
接口SingletonBeanRegistry粪薛,負(fù)責(zé)對(duì)單例進(jìn)行注冊(cè),以及獲取單例等跟單例等相關(guān)的方法搏恤。這說(shuō)明beanFactory有專門(mén)處理單例對(duì)象的邏輯违寿。
public interface SingletonBeanRegistry {
void registerSingleton(String beanName, Object singletonObject);
Object getSingleton(String beanName);
boolean containsSingleton(String beanName);
String[] getSingletonNames();
int getSingletonCount();
}
接口AliasRegistry,負(fù)責(zé)別名注冊(cè)相關(guān)的方法熟空。這個(gè)接口說(shuō)明beanFactory可以為bean注冊(cè)別名藤巢,可以讓用戶通過(guò)別名訪問(wèn)bean的相關(guān)信息。SimpleAliasRegistry為AliasRegistry的具體類(lèi)息罗,不出意外掂咒,該類(lèi)在后續(xù)肯定是協(xié)助DefaultListableBeanFactory代理執(zhí)行AliasRegistry的這幾個(gè)方法。
public interface AliasRegistry {
void registerAlias(String name, String alias);
void removeAlias(String alias);
boolean isAlias(String beanName);
String[] getAliases(String name);
}
接口BeanDefinitionRegistry迈喉,負(fù)責(zé)bean定義信息注冊(cè)相關(guān)的方法绍刮。
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String beanName);
}
DefaultSingletonBeanRegistry,這是個(gè)具體類(lèi)挨摸,繼承自SimpleAliasRegistry和SingletonBeanRegistry孩革。該類(lèi)主要負(fù)責(zé)實(shí)現(xiàn)SingletonBeanRegistry接口中所有的方法。同時(shí)得运,它還實(shí)現(xiàn)了很多其他關(guān)于bean的方法膝蜈,其中包括注冊(cè)bean的依賴關(guān)系,還有bean的銷(xiāo)毀方法熔掺,其中由于包含依賴饱搏,所以多個(gè)方法都是遞歸實(shí)現(xiàn)的。該類(lèi)只負(fù)責(zé)管理和注冊(cè)bean信息置逻,同時(shí)也包含創(chuàng)建bean的功能窍帝。整體類(lèi)功能非常具體且獨(dú)立,所以閱讀起來(lái)也很簡(jiǎn)單诽偷,由于該類(lèi)方法較多,就不貼代碼了疯坤。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
...
}
接口ConfigurableBeanFactory报慕,繼承自HierarchicalBeanFactory, SingletonBeanRegistry,接口中主要是配置beanFactory信息的接口压怠,同時(shí)因?yàn)槔^承自SingletonBeanRegistry眠冈,也包含該接口相關(guān)方法。
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry
抽象類(lèi)FactoryBeanRegistrySupport,繼承自DefaultSingletonBeanRegistry蜗顽。該抽象類(lèi)沒(méi)包含抽象方法布卡,所以僅僅只是不能實(shí)例化。該類(lèi)新增了幾個(gè)方法未包含public方法雇盖,說(shuō)明該類(lèi)僅僅是為了給子類(lèi)提供工具方法忿等,新增方法主要是bean和beanFactory相關(guān)方法。
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry
AbstractBeanFactory抽象類(lèi)
AbstractBeanFactory抽象類(lèi)繼承自FactoryBeanRegistrySupport崔挖,ConfigurableBeanFactory贸街。該類(lèi)主要實(shí)現(xiàn)了BeanFactory接口中的方法,HierarchicalBeanFactory接口中的方法狸相,以及ConfigurableBeanFactory接口中的方法薛匪。最后,該類(lèi)提供了三個(gè)抽象方法交給子類(lèi)實(shí)現(xiàn)脓鹃。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory
BeanFactory接口方法實(shí)現(xiàn)
AbstractBeanFactory抽象類(lèi)實(shí)現(xiàn)了beanFactory的方法逸尖,用來(lái)獲取bean的getBean方法以及一些與bean狀態(tài)和類(lèi)型相關(guān)的方法。比較重要的有g(shù)etBean方法瘸右,getBean方法實(shí)際調(diào)用的是doGetBean方法娇跟,因?yàn)閎ean之間可能存在依賴,所以doGetBean方法中生成bean的時(shí)候是遞歸進(jìn)行的尊浓,真正生成bean對(duì)象的是createBean方法逞频,該方法為抽象方法,由子類(lèi)負(fù)責(zé)實(shí)現(xiàn)栋齿。
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 {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
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);
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
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;
}
}
// Check if required type matches the type of the actual bean instance.
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;
}
ConfigurableBeanFactory接口實(shí)現(xiàn)
該接口實(shí)現(xiàn)主要包含配置化beanFactory接口的實(shí)現(xiàn)苗胀。
AbstractBeanFactory的抽象方法
protected abstract boolean containsBeanDefinition(String beanName);
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
throws BeanCreationException;
AbstractAutowireCapableBeanFactory抽象類(lèi)
該抽象類(lèi)繼承自AbstractBeanFactory和AutowireCapableBeanFactory,實(shí)現(xiàn)了AbstractBeanFactory的抽象方法creatBean瓦堵,并且實(shí)現(xiàn)了繼承自AutowireCapableBeanFactory的接口基协,提供了bean的創(chuàng)建奕剃,屬性填充授舟,自動(dòng)裝配等功能。
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory
了解了DefaultListableBeanFactory的繼承層次后艺蝴,可以知道DefaultListableBeanFactory負(fù)責(zé)的功能:bean信息的注冊(cè)惋鸥、bean的獲取杂穷、bean的創(chuàng)建,同時(shí)卦绣,也支持了自動(dòng)裝配等功能耐量,同時(shí)還實(shí)現(xiàn)了插件BeanPostProcessor,初步來(lái)看滤港,這個(gè)beanPostProcessor可以用戶實(shí)現(xiàn)注入到該框架當(dāng)中增強(qiáng)spring的功能廊蜒,還有一些其他功能并未細(xì)看,等到用到時(shí)候再詳細(xì)解讀。
至此山叮,DefaultListableBeanFactory已經(jīng)大致了解清楚著榴。
createBeanFactory調(diào)用結(jié)束后,loadBeanDefinitions(beanFactory)是更重要的方法屁倔,因?yàn)閯?chuàng)建出來(lái)的beanFactory對(duì)象還并未真正進(jìn)行xml配置解析和信息的填充脑又。
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
loadBeanDefinitions方法在AbstractXmlApplicationContext中繼承后實(shí)現(xiàn),該方法進(jìn)一步調(diào)用XmlBeanDefinitionReader來(lái)解析bean信息汰现,解析后填充到beanFactory對(duì)象中挂谍,由于該方法內(nèi)部調(diào)用較為復(fù)雜,涉及相當(dāng)多的對(duì)象瞎饲,需要單列一章介紹口叙。
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
bean定義信息加載完成后,obtainFreshBeanFactory方法執(zhí)行完成嗅战。
prepareBeanFactory(beanFactory)
beanFactory對(duì)象在此方法中妄田,設(shè)置了多個(gè)屬性。
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());
}
}
postProcessBeanFactory(beanFactory)
空方法驮捍,需要子類(lèi)繼承實(shí)現(xiàn)才能生效疟呐。
未完待續(xù)。