Spring IOC容器分析(1) -- BeanFactory


搭建好源碼閱讀環境后,就可以慢慢走進Spring殿堂了。IOC是Inversion of Control的縮寫,控制反轉的意思。很多人可能都知道IOC是spring的核心,將對象的創建初始化等權限交由容器控制,從而減少對象之間的依賴。甚至聽說過BeanFactory,知道BeanFactory是實現IOC機制的核心,但是具體如何實現,卻不是十分清楚。下面我們來一步一步深入理解BeanFactory。

引例

在spring工程應用中,一般用spring注解@Autowired來自動加載依賴對象,如下所示:

public class MerchantController {

	@Autowired
    private final MerchantService merchantService;
}

注解@Autowired使得對象加載很方便,使得對象依賴間管理很容易。但是依據守恆定律,對象的加載、創建、初始化等步驟是不會減少的,這里使用簡單了,那必然在別的地方執行了對象的加載、創建、初始化的過程。實際上這個加載、創建、初始化的過程是在Spring源碼BeanFactory中完成的。

BeanFactory

首先看下BeanFactory源碼,BeanFactory是一個祖宗級接口,定義了Bean Factory的各種基本方法。spring中各種具體bean工廠均是對BeanFactory接口的實現,如DefaultListableBeanFactory,SimpleJndiBeanFactory,StaticListableBeanFactory等。

作為一個接口,BeanFactory定義的方法非常簡單,而且都是一些常用的方法模板,如:getBean()containsBean()isSingleton()方法。BeanFactory接口如下:

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;

public interface BeanFactory {

	String FACTORY_BEAN_PREFIX = "&";

	Object getBean(String name) throws BeansException;

	<T> T getBean(String name, Class<T> requiredType) throws BeansException;

	<T> T getBean(Class<T> requiredType) throws BeansException;

	Object getBean(String name, Object... args) throws BeansException;

	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

	boolean containsBean(String name);

	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

	Class<?> getType(String name) throws NoSuchBeanDefinitionException;

	String[] getAliases(String name);
}

顧名思義,getBean()方法是用來獲取Bean工廠中存儲的對象實例,根據name即可獲得對應的對象,也即是配置文件(暫認為xml)中定義的idcontainsBean是用於判斷該Bean工廠中是否含有name所對應的對象。isSingleton是判斷該name所對應的Bean是否是共享的單例,如果true的話,當調用getBean()方法時便會返回該Bean。

getBean()方法,應該能夠猜測出:Bean工廠是先將name-bean作為一個鍵值對存儲在一個容器中,當調用getBean()方法時,根據key值取出對應的bean值。實際上,spring中的確是這么做的。

根據UML類圖關系,找到BeanFactory接口對應的默認實現類DefaultListableBeanFactory,如下圖所示。

DefaultListableBeanFactoryUML類圖關系

查看DefaultListableBeanFactory源碼,發現:屬性中beanDefinitionMap用於存儲name-bean鍵值對,也即是存放Bean工廠實例化后的bean。截取部分源碼如下:

package org.springframework.beans.factory.support;

@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	............
	/** Map of bean definition objects, keyed by bean name */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
	...........
}

從源碼可以發現,存儲鍵值對的容器是ConcurrentHashMap,它是一個基於HashMap的高並發容器,具有很好的線程安全性。其存儲的不是String-Object鍵值對,而是String-BeanDefinition鍵值對,也就是說創建的bean對象不是以Object類型存儲的,而是Bean Definition類型存儲。為什么是這樣的呢?請聽下回分解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM