Spring IOC-BeanFactory的繼承體系結構
本文主要介紹BeanFactory以及它的各種繼承層級的介面、抽象類及實現類,因為內容很多,所以這裡不介紹ApplicationContext繼承體系下的類(雖然ApplicationContext本質上也是BeanFactory,但是畢竟這這是我們平時接觸最多的兩種類別,所以分開說)。
關於ApplicationContext繼承體系結構在《Spring IOC-ApplicationContext的繼承體系結構》一文分享說明。
BeanFactory其實就是Spring的IOC容器,當然了Spring為我們準備了許多種IOC容器來使用,這樣可以方便我們從不同的層面,不同的資源位置,不同的形式的定義資訊來建立我們需要的IoC容器。
在鄙人部落格的不同的博文中其實都提到了Spring的一個設計理念,就是介面-抽象類-實現類的體系結構,這裡多說幾句為什麼這麼設計,熟悉設計模式的人都知道,這樣的目的是為了提高軟體的可維護性、可擴充套件性、強複用性。說的文雅一點就是使程式碼滿足“對修改關閉、對擴充套件開放”、“里氏代換”原則 、“依賴倒轉”原則、“介面隔離”原則、“合成\聚合複用”原則。如果項瞭解這幾個原則可以百度下,這裡不詳細介紹。
廢話不多說,直接上程式碼來看下BeanFactory的繼承道理多屌。
先貼張圖,由於是手工畫的,很粗糙,大家大致看下知道下面介紹的類大概在繼承體系的哪個位置。
首先看BeanFactory介面中定義的方法:
public interface BeanFactory {
//這裡是對FactoryBean的轉義定義,因為如果使用bean的名字檢索FactoryBean得到的物件是工廠生成的物件
String FACTORY_BEAN_PREFIX = "&";
//這裡根據bean的名字,在IOC容器中得到bean例項,這個IOC容器就是一個大的抽象工廠。
Object getBean(String name) throws BeansException;
//這裡根據bean的名字和Class型別來得到bean例項,和上面的方法不同在於它會丟擲異常:如果根據名字取得的bean例項的Class型別和需要的不同的話。
<T> T getBean(String name, Class<T> requiredType);
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
//這裡提供對bean的檢索,看看是否在IOC容器有這個名字的bean
boolean containsBean(String name);
//這裡根據bean名字得到bean例項,並同時判斷這個bean是不是單件
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//這裡根據bean名字得到bean例項,並同時判斷這個bean是不是原型
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
//這裡對得到bean例項的Class型別
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
//這裡得到bean的別名,如果根據別名檢索,那麼其原名也會被檢索出來
String[] getAliases(String name);
然後在看BeanFactory 的直接繼承介面(二級介面),有HierarchicalBeanFactory、AutowireCapableBeanFactory和ListableBeanFactory看這三個類程式碼:
- HierarchicalBeanFactory
作用:是為了實現bean工廠的層級關係提供支援,其中宣告兩個方法:
//得到父工廠
BeanFactory getParentBeanFactory();
//在本地工廠中有沒有給定名稱的bean,不包括繼承的工廠
boolean containsLocalBean(String name);
- AutowireCapableBeanFactory
作用:提供自動裝配bean能力的功能支援,宣告方法如下:(這個介面中所有宣告的方法都是在預設的實現實在AbstractAutowireCapableBeanFactory類中預設實現)
//用個給定的class型別製造一個完整的bean
<T> T createBean(Class<T> beanClass) throws BeansException;
//bean初始化完成之後執行回撥函式和後處理器,
void autowireBean(Object existingBean) throws BeansException;
// 自動注入和設定bean的屬性、執行factory回撥函式比如setBeanName和setBeanFactory和執行bean的所有的後處理器
Object configureBean(Object existingBean, String beanName) throws BeansException;
//呼叫bean的init方法,這個方法是客戶配置的,在bean例項化之後呼叫
Object initializeBean(Object existingBean, String beanName) throws BeansException;
//初始化完成之後應用後處理器
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
//應用前處理器
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName);
- ListableBeanFactory
作用:可以列舉所有的bean例項,是為了使客戶端訪問工廠中的bean而設計的,主要方法(這些方法顧名思義,所有的方法實現在StaticListableBeanFactory、AbstractApplicationContext和DefaultListableBeanFactory中):
//是否含有給定的名稱的bean
boolean containsBeanDefinition(String beanName);
int getBeanDefinitionCount();
//得到工廠所有的bean的名稱陣列
String[] getBeanDefinitionNames();
String[] getBeanNamesForType(Class<?> type);
//根據給定的型別得到和相應的策略得到所有的bean名稱陣列
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
//根據給定過的型別得到所有該型別的bean,返回的結果是一個Map<bean名稱,bean物件>的形式
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
//得到給定名稱的bean上的給定註解型別的註解物件
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType);
下面我們介紹BeanFactory 的三級介面,看繼承關係圖知道是ConfigurableBeanFactory和ConfigurableListableBeanFactory。
- ConfigurableBeanFactory
作用: 實現可配置的bean的環境功能,這個介面繼承自HierarchicalBeanFactory所以支援層級關係的工廠,和SingletonBeanRegistry所以肯定支援單例工廠行為,看主要方法程式碼(在AbstractBeanFactory類中預設實現):
void setConversionService(ConversionService conversionService);
void setTypeConverter(TypeConverter typeConverter);
//支援自定義bean的作用範圍,可以理解為單例和多例之外的
void registerScope(String scopeName, Scope scope);
//歸併的將給定的name的bean的定義
BeanDefinition getMergedBeanDefinition(String beanName);
//新增處理器
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
//下面是3個destory方法
void destroyBean(String beanName, Object beanInstance);
void destroyScopedBean(String beanName);
//只能銷燬所有單例的bean,因為多例的是不歸Spring控制的,是由客戶端控制的
void destroySingletons();
- ConfigurableListableBeanFactory
作用:提供可配置的、可訪問的功能,介面中的方法在在DefaultListableBeanFactory預設實現預設實現。
public interface ConfigurableListableBeanFactory
extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
//凍住之後bean定義就不能在被修改和進行任何的後處理器規定的操作
void freezeConfiguration();
//確保所有的單例bean都例項化
void preInstantiateSingletons() throws BeansException;
//
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
//判斷當前的bean是不是作為其它bean的依賴注入的
boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor);
上面是介面的繼承體系和說明,下面來介紹介面下抽象類的程式碼,在上面的介紹中我們知道就兩個抽象類AbstractAutowireCapableBeanFactory和AbstractBeanFactory,先看繼承關係:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
可以知道AbstractAutowireCapableBeanFactory 是AbstractBeanFactory 類的子類。通過上面的介面和抽象類的介紹我們將研究的重點轉到轉到這兩個抽象類中。
這裡我們主要看bean工廠是怎麼將xml中的定義資訊轉換為互相依賴的bean定義或者初始化為實體物件。
先看在繼承體系偏上的類AbstractBeanFactory ,這個類最重要的是對BeanFactory中getBean()的實現,直接看實現的程式碼:
………………
public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
return doGetBean(name, requiredType, args, false);
}
在看doGetBean()方法程式碼:
………………
//首先從單例工廠得到有沒有
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//不是但單例的
else {
//看是不是在父BeanFactory ,因為實現了HierarchicalBeanFactory介面
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
……………………
if (mbd.isSingleton()) {//單例的
//用回撥的形式建造bean並且放入單例工廠
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
……………………
//多例的
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
………………
else {//沒有明確是單例的還是不是,有自己的作用域scope
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return createBean(beanName, mbd, args);
……………………
可以上面是分為三種情況得到bean的,單例的、多例的、Scope的。但是所有的情況最終都定位到一個方法——createBean(beanName, mbd, args),這個方法在AbstractBeanFactory 是抽象的protected abstract Object createBean(
,很明顯,只能在子類中實現,自然就要看AbstractAutowireCapableBeanFactory 中的建造bean的createBean()程式碼:
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
………………
//如果沒有找到這個name的class型別是會丟擲異常的
resolveBeanClass(mbd, beanName);
//判斷在xml中定義的overrides方法存在
mbd.prepareMethodOverrides();
………………
//用bean的前處理器去例項化
Object bean = resolveBeforeInstantiation(beanName, mbd);
………………
Object beanInstance = doCreateBean(beanName, mbd, args);
………………
好的,程式碼定位到doCreateBean(beanName, mbd, args)方法:
//逐漸的構造一個bean,分別用factory method, and autowiring a constructor.去構造,這些都是在xml中配置的。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
………………
instanceWrapper = createBeanInstance(beanName, mbd, args);
………………
//構造bean並且注入依賴所有bean的屬性值
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//呼叫配置的init方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
程式碼定位到createBeanInstance(beanName, mbd, args)
//用 factory method, constructor autowiring, or simple instantiation.三種方法去例項化一個bean
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
………………
//用getFactoryMethodName去例項化一個
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
………………
//用建構函式
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}else {
//用預設的建構函式得到
return instantiateBean(beanName, mbd);
}
………………
}
再定位程式碼到populateBean(beanName, mbd, instanceWrapper):
//主要是bean中的成員變數的初始化和注入,《依賴的注入》
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
……………………
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
……………………
//將屬性的引用和具體的物件結合起來,用到了java的反射機制
applyPropertyValues(beanName, mbd, bw, pvs);
}
最後是applyPropertyValues(beanName, mbd, bw, pvs)
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
try {
//呼叫BeanWrapper類的方法
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
這裡補充一下BeanWrapperImpl類中設定屬性依賴的程式碼實現:
………………
//如果有key屬性配置,證明是array list 或者map
if (tokens.keys != null) {
if (propValue.getClass().isArray()) {
else if (propValue instanceof List) {
else if (propValue instanceof Map) {
}
//普通的屬性設定
else{
………………
writeMethod.setAccessible(true);
writeMethod.invoke(object, value);
}
………………
至此bean的如何初始化和如何進行依賴注入就已經研究程式碼完畢。
下面也是最後我們看一下這個繼承體系中具體類XmlBeanFactory、DefaultListableBeanFactory的實現程式碼:
- XmlBeanFactory
//這個類的實現很簡單,只是委託XmlBeanDefinitionReader進行xml的讀取和配置資訊的載入
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
// 構造的時候就進行xml檔案的解析
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
- DefaultListableBeanFactory
是XmlBeanFactory的父類,也就是而你看下文章最前面的繼承圖,你會發現DefaultListableBeanFactory擁有這個繼承體系中的所有功能。
那麼除了繼承父類的功能方法外,它獨特的功能在於對ConfigurableListableBeanFactory和ListableBeanFactory介面的實現。