spring IOC容器的實現,一開始我被復雜的接口和類所掩埋,看不清整體的思路和設計,踟躕于代碼叢林中,摸不清前進的方向。一開始我就決定只研讀以xml文件做配置文件的XmlFactoryBean的具體實現為主要目標,漸漸地有了點感覺,用UML把spring中的bean工廠體系展現出來之后就更清晰了,讓你不得不感嘆設計的精巧和復雜。本文只是我個人對spring IOC實現的理解,如有錯誤,請不吝賜教,謝謝。
首先,需要理解的是spring容器中bean的生命周期,《spring in action》中的那張圖是最好的解釋,結合這張圖和源碼來解讀spring中IOC的實現將非常容易理解。這張圖完整展示了spring容器中一個bean從創建到銷毀的整個生命周期。

1. 容器尋找Bean的定義信息并且將其實例化。
2.受用依賴注入,Spring按照Bean定義信息配置Bean的所有屬性。
3.如果Bean實現了BeanNameAware接口,工廠調用Bean的setBeanName()方法傳遞Bean的ID。
4.如果Bean實現了BeanFactoryAware接口,工廠調用setBeanFactory()方法傳入工廠自身。
5.如果BeanPostProcessor和Bean關聯,那么它們的postProcessBeforeInitialzation()方法將被調用。
6.如果Bean指定了init-method方法,它將被調用。
7.最后,如果有BeanPsotProcessor和Bean關聯,那么它們的postProcessAfterInitialization()方法將被調用。
到這個時候,Bean已經可以被應用系統使用了,并且將被保留在Bean Factory中知道它不再需要。有兩種方法可以把它從Bean Factory中刪除掉。
1.如果Bean實現了DisposableBean接口,destory()方法被調用。
2.如果指定了訂制的銷毀方法,就調用這個方法。
下面我們將會看到,這些bean創建銷毀的每個階段是如何在源碼中實現的。
再看看spring中bean工廠的完整體系,比較復雜,不過我們只需要關注其中的幾個核心工廠。
(看不清楚,請
下載圖片來看,比較清晰)
這些工廠類沒有在同一個包內,分布在org.springframework.beans以及它的子包內,把它們放在一起就看的比較清楚了。我們需要關注的是這么兩個類:org.springframework.beans.factory.support.AbstractBeanFactory
org.springframework.beans.factory.support.DefaultListableBeanFactory
以及接口:
org.springframework.beans.factory.support.BeanDefinitionRegistry
AbstractBeanFactory作為BeanFactory接口的抽象實現類,是其他工廠類的父類,提供了bean的singlton緩存、singleton/prototype的決定、bean的別名以及bean和它的子類bean的定義合并(bean definition merging for child bean definitions)和銷毀。這里有3個重載的getBean方法(實現BeanFactory定義的getBean方法),我們關注下最主要的這個方法:
public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {
String beanName = transformedBeanName(name);
Object bean = null;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = null;
//從單例緩存中獲取
synchronized (this.singletonCache) {
sharedInstance = this.singletonCache.get(beanName);
}
if (sharedInstance != null) {
if (isSingletonCurrentlyInCreation(beanName)) {
if (logger.isDebugEnabled()) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForSharedInstance(name, sharedInstance);
}
else {
// Fail if we're already creating this singleton instance:
// We're assumably within a circular reference.
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//檢測bean是否定義在父工廠
if (getParentBeanFactory() != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
if (getParentBeanFactory() instanceof AbstractBeanFactory) {
// Delegation to parent with args only possible for AbstractBeanFactory.
return ((AbstractBeanFactory) getParentBeanFactory()).getBean(name, requiredType, args);
}
else if (args == null) {
// No args -> delegate to standard getBean method.
return getParentBeanFactory().getBean(name, requiredType);
}
else {
throw new NoSuchBeanDefinitionException(beanName,
"Cannot delegate to parent BeanFactory because it does not supported passed-in arguments");
}
}
//獲取BeanDefinition
RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition(beanName, false);
checkMergedBeanDefinition(mergedBeanDefinition, beanName, requiredType, args);
// Create bean instance.
//創建bean,如果為為singleton
if (mergedBeanDefinition.isSingleton()) {
synchronized (this.singletonCache) {
// Re-check singleton cache within synchronized block.
sharedInstance = this.singletonCache.get(beanName);
if (sharedInstance == null) {
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
this.currentlyInCreation.add(beanName);
try {
sharedInstance = createBean(beanName, mergedBeanDefinition, args);
//加進單例緩存
addSingleton(beanName, sharedInstance);
}
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.
destroyDisposableBean(beanName);
throw ex;
}
finally {
this.currentlyInCreation.remove(beanName);
}
}
}
bean = getObjectForSharedInstance(name, sharedInstance);
}
//如果是prototype
else {
// It's a prototype -> create a new instance.
bean = createBean(beanName, mergedBeanDefinition, args);
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isAssignableFrom(bean.getClass())) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return bean;
}
當你調用getBean獲取一個bean的時候,spring首先查找單例緩存中是否已經有這個bean,有的話直接返回(首先會判斷是否已經創建),如果沒有,spring就開始創建這個bean:首先獲取bean的定義(BeanDefinition),檢測bean是否定義在父工廠中,有的話調用父工廠的getBean方法;沒有就檢測bean是singleton還是prototype,如果是singleton就是創建bean并加入緩存以便下次直接調用,如果是prototype,就在每次調用時重新創建一個bean實例。注意createBean(beanName, mergedBeanDefinition, args); 這個方法,這是創建bean的核心方法,并且是一個abstract方法,將被子類實現。
看看是如何獲取bean的定義的,
protected RootBeanDefinition getMergedBeanDefinition(String name, boolean includingAncestors)
throws BeansException {
String beanName = transformedBeanName(name);
// Efficiently check whether bean definition exists in this factory.
if (includingAncestors && !containsBeanDefinition(beanName) &&
getParentBeanFactory() instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName, true);
}
// Resolve merged bean definition locally.
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
調用重載的getMergedBeanDefinition合并父工廠和子工廠中的bean定義,注意getBeanDefinition(beanName),這是一個抽象方法,延遲到子類實現以便提供獲取bean定義的具體方法,這個方法和 createBean 一樣都是template method模式的應用。看看它們的定義:
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
protected abstract Object createBean(
String beanName, RootBeanDefinition mergedBeanDefinition, Object[] args) throws BeanCreationException;
基本了解了AbstractBeanFactory 后,我們來看看它的子類的AbstractAutowireCapableBeanFactory ,這個類實現了createBean() ,在這個方法中我們將看到與
上面bean的生命周期圖對應的
bean的創建過程,英文注釋已經非常清楚:
protected Object createBean(String beanName, RootBeanDefinition mergedBeanDefinition, Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName +
"' with merged definition [" + mergedBeanDefinition + "]");
}
Object bean = null;
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
if (mergedBeanDefinition.hasBeanClass()) {
bean = applyBeanPostProcessorsBeforeInstantiation(mergedBeanDefinition.getBeanClass(), beanName);
if (bean != null) {
return bean;
}
}
// Guarantee initialization of beans that the current one depends on.
if (mergedBeanDefinition.getDependsOn() != null) {
for (int i = 0; i < mergedBeanDefinition.getDependsOn().length; i++) {
getBean(mergedBeanDefinition.getDependsOn()[i]);
}
}
BeanWrapper instanceWrapper = null;
Object originalBean = null;
String errorMessage = null;
try {
// Instantiate the bean.
errorMessage = "Instantiation of bean failed";
if (mergedBeanDefinition.getFactoryMethodName() != null) {
instanceWrapper = instantiateUsingFactoryMethod(beanName, mergedBeanDefinition, args);
}
else if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mergedBeanDefinition.hasConstructorArgumentValues() ) {
instanceWrapper = autowireConstructor(beanName, mergedBeanDefinition);
}
else {
// No special handling: simply use no-arg constructor.
instanceWrapper = instantiateBean(beanName, mergedBeanDefinition);
}
bean = instanceWrapper.getWrappedInstance();
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
if (isAllowCircularReferences() && isSingletonCurrentlyInCreation(beanName)) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean with name '" + beanName +
"' to allow for resolving potential circular references");
}
addSingleton(beanName, bean);
}
// Initialize the bean instance.
errorMessage = "Initialization of bean failed";
populateBean(beanName, mergedBeanDefinition, instanceWrapper);
if (bean instanceof BeanNameAware) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking setBeanName on BeanNameAware bean '" + beanName + "'");
}
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanFactoryAware) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking setBeanFactory on BeanFactoryAware bean '" + beanName + "'");
}
((BeanFactoryAware) bean).setBeanFactory(this);
}
originalBean = bean;
bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
invokeInitMethods(beanName, bean, mergedBeanDefinition);
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mergedBeanDefinition.getResourceDescription(), beanName, errorMessage, ex);
}
// Register bean as disposable, and also as dependent on specified "dependsOn" beans.
registerDisposableBeanIfNecessary(beanName, originalBean, mergedBeanDefinition);
return bean;
}
通過instanceof操作符來判斷bean是否實現了用于生命周期回調的接口,然后調用相應的回調方法,可以看到spring充分實踐了針對接口編程的原則,雖然很夸張的一個方法一個接口的地步,不過這些接口也是作為mark interface用于標記回調。結合上面的生命周期圖看這段代碼將很好理解。有了bean的創建方法,那么如何獲取bean在配置文件中的定義信息呢?也就是在哪里實現了 getBeanDefinition方法呢?答案就在AbstractAutowireCapableBeanFactory 的子類DefaultListableBeanFactory中。
DefaultListableBeanFactory 不僅繼承了AbstractAutowireCapableBeanFactory ,還實現了BeanDefinitionRegistry和ConfigurableListableBeanFactory接口。其中ConfigurableListableBeanFactory接口是定義了分析和修改bean定義信息的回調方法,暫時不去管它。看看BeanDefinitionRegistry接口:
public interface BeanDefinitionRegistry {
int getBeanDefinitionCount();
String[] getBeanDefinitionNames();
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
String[] getAliases(String beanName) throws NoSuchBeanDefinitionException;
void registerAlias(String beanName, String alias) throws BeansException;
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeansException;
......
}
一系列用于獲取bean定義信息的方法,這個接口我們將在后面的代碼中看到,作為一個mark inteface。注意咯,這個接口中非常關鍵的一個方法就是registerBeanDefinition,這個方法用于向bean工廠注冊解析的每個bean定義,我們將在xml文件的解析的環節看到調用這個方法注冊bean定義信息。
DefaultListableBeanFactory實現了BeanDefinitionRegistry 接口,可以看到它實現了關鍵的registerBeanDefinition用于將bean的定義注冊到工廠類中,其中維護了一個Map用于存儲bean的定義信息:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "Bean definition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': there's already [" + oldBeanDefinition + "] bound");
}
else {
if (logger.isInfoEnabled()) {
logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
}
this.beanDefinitionMap.put(beanName, beanDefinition);
// Remove corresponding bean from singleton cache, if any.
// Shouldn't usually be necessary, rather just meant for overriding
// a context's default beans (e.g. the default StaticMessageSource
// in a StaticApplicationContext).
removeSingleton(beanName);
}
beanDefinitionMap就是我們存儲工廠類中注冊的bean的信息,用bean name做為key:
/** Map of bean definition objects, keyed by bean name */
private final Map beanDefinitionMap = new HashMap();
DefaultListableBeanFactory 重寫了
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
模板方法用于提供bean定義信息給getBean方法用于創建bean實例。getBeanDefinition的從beanDefinitionMap 查找bean定義即可:
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
BeanDefinition bd = (BeanDefinition) this.beanDefinitionMap.get(beanName);
if (bd == null) {
if (logger.isDebugEnabled()) {
logger.debug("No bean named '" + beanName + "' found in " + toString());
}
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}
看到了這里是不是覺的有點糊涂,我還是建議有興趣地找來spring1.2的源碼來看看就很清晰了,充分利用eclipse的F3跳轉結合上面的那張UML圖。
OK,有了注冊bean定義信息的方法(registerBeanDefinition),有了獲取bean定義信息的方法(getBeanDefinition ),有了創建bean的方法(createBean),那么在哪里調用這些方法呢?createBean我們已經知道是在BeanFactory的getBean方法時調用,getBeanDefinition 又是在creatBean時調用用于獲取bean的定義信息,那么注冊bean定義信息的方法肯定是在xml文件解析階段被調用。
XmlBeanFactory繼承DefaultListableBeanFactory ,沒有定義新的方法,只是有兩個重載的構造函數:
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
初始化XmlBeanFactory時調用XmlBeanDefinitionReader讀取xml配置文件,而XmlBeanDefinitionReader的loadBeanDefinitions方法,載入xml文件并且調用XmlBeanDefinitionParser 解析xml文件同時注冊bean定義信息到bean工廠,這幾個類的協作以及它們繼承體系也非常清晰,在此不再詳述(累啊),XmlBeanDefinitionParser是一個接口,具體的實現類是org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser,我們關注的就是它是怎么注冊bean信息到bean工廠的:
protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException {


if (IMPORT_ELEMENT.equals(node.getNodeName())) {
importBeanDefinitionResource(ele);
}
else if (ALIAS_ELEMENT.equals(node.getNodeName())) {
String name = ele.getAttribute(NAME_ATTRIBUTE);
String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
this.beanDefinitionReader.getBeanFactory().registerAlias(name, alias);
}
else if (BEAN_ELEMENT.equals(node.getNodeName())) {
beanDefinitionCount++;
BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false);
//關鍵代碼,調用工具類將bean定義注冊到beanFactory
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.beanDefinitionReader.getBeanFactory());
}

}
工具類BeanDefinitionReaderUtils中的注冊方法:
public static void registerBeanDefinition(
BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory) throws BeansException {
// Register bean definition under primary name.,注冊bean
beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition());
// Register aliases for bean name, if any.,注冊別名
if (bdHolder.getAliases() != null) {
for (int i = 0; i < bdHolder.getAliases().length; i++) {
beanFactory.registerAlias(bdHolder.getBeanName(), bdHolder.getAliases()[i]);
}
}
}
注意這里的beanFactory是BeanDefinitionRegistry類型 ,DefaultListableBeanFactory實現了這個接口。
更多內容,比如spring是怎么把bean的屬性注入的?答案在BeanWrapperImpl中的一系列setPropertyXXX方法。BeanFactory是如何實例化bean的呢?具體展開請看org.springframework.beans.factory.support.InstantiationStrategy 接口,一個典型的策略模式的應用,兩個實現類:SimpleInstantiationStrategy和CglibSubclassingInstantiationStrategy。我們知道spring有3種注入方式:setter、構造函數以及Method Inject。這里的CglibSubclassingInstantiationStrategy使用cglib庫用于實現method inject。這樣一篇小文容不下這么多內容,還是有興趣的自己找源碼讀讀。
寫到這里,我對自己的文字表達能力產生懷疑,我能不能把這些所有的信息都說清楚呢?感覺很不滿意,將就吧,也算是自己的學習總結。
讀spring源碼這段時間,最深的幾點體會:
1)單元測試非常重要,充分感受到了單元測試作為項目文檔的優勢。看不懂一個類,找到這個類的測試類就OK!
2)針對接口編程的原則,spring處處體現了這個原則,繁多的接口帶來的是松耦合、高內聚并且易于擴展的架構,但也帶來了一定的理解難度。作為通用型框架也許需要這么考慮,在實際項目中的取舍還是要自己把握。
3)設計模式的使用,spring中應用了很多模式,比如template method,比如strategy和factory method、visitor、singleton等,簡直是一本模式實踐的良好教材。