聲明:我已委託「維權騎士」(rightknights.com)爲個人文章進行維權行動。java
經過上一章《理解Spring系列——什麼是控制反轉(Inversion of Control, IoC)》,咱們瞭解到IoC編程模式的本質,經過協議約定來分離when-to-do和what-to-do兩個關注點,實現模塊間的解耦。git
而在Spring Framework中,BeanFactory絕對是Spring IoC的核心擔當:BeanFactory
在Spring中的主要做用,經過抽象Bean實例化的具體過程(體如今BeanDefinition定義),藉助依賴注入(Dependency Inject,DI)的能力,實現基於元數據的業務對象自動裝配,能夠理解成加強版的Guice,以下圖所示。github
在Spring Framework中,BeanFactory
做爲很是基礎的接口存在,提供了Bean註冊能力(包括Bean查詢、類型判斷、scope判斷等基礎能力);在繼承體系上,能夠分紅BeanFactory實現類
和ApplicationContext
兩條繼承線路。web
二者的關係以下:BeanFactory實現類
屬於外觀模式的子系統(SubSystem)承擔着外界提供Bean對象的主要責任,是功能實現的主體;ApplicationContext
做爲BeanFactory實現類
的外觀系統(Facade System),經過 BeanFactory
提供的接口結合具體的業務場景解析元數據(BeanDefinition
)的解析和註冊,並進行Bean對象的初步加載。 另外,ApplicationContext
繼承於接口 BeanFactory
,並在BeanFactory
的基礎上,提供AoP能力的集成、消息資源的管理、事件發佈機制、以及基於特定場景(Web系統、文件系統)的能力封裝等主要功能。spring
BeanFactory
完整的繼承關係以下圖所示: 編程
從圖中能夠看出,BeanFactory
的主要實現類包括StaticListableBeanFactory
、DefaultListableBeanFactory
、SimpleJndiBeanFactory
等三個公共類,分別面向靜態場景、默認枚舉配置場景和JNDI等場景,對應的實現思路也不盡相同。app
StaticListableBeanFactory
能夠看作是基於Map<String,Object>
的簡單封裝,不包括Bean的實例化過程,須要用戶手動註冊後纔可使用,不具有依賴注入能力,是BeanFactory
最爲簡單的實現;DefaultListableBeanFactory
是Spring BeanFactory
的默認實現,是Spring IoC容器中最爲複雜的部分,在後續的章節咱們會進行分析;SimpleJndiBeanFactory
則是基於JNDI場景發現對應Bean。類 DefaultListableBeanFactory 的繼承關係以下圖所示, 從中咱們能夠基本上了解到 類 DefaultListableBeanFactory 的基本功能。post
DefaultListableBeanFactory
的接口繼承關係從接口實現上看,類 DefaultListableBeanFactory 主要實現瞭如下基礎的接口:ui
AliasRegistry
:屬於spring-core模塊(別名能力不限制於Bean Name場景,所以定義在core模塊中),提供String類型別名相關能力,對應的實現類爲 SimpleAliasRegistry ,能夠看作是簡易版的 Map<String,String> 抽象能力,提供別名的增刪改查相關能力;google
SingletonBeanRegistry
:屬於spring-beans模塊,提供單例bean對象的註冊和查詢能力,能夠看作是簡易版的 Map<String,Object> ;
ListableBeanFactory:
:屬於spring-beans模塊,在 BeanFactory 的基礎上提供更進一步的非精確化查詢能力,支持基於類型( Class
和 ResolvableType
)的查詢能力,返回的結果支持beanName 和Map<BeanName,Bean>
;
HierarchicalBeanFactory
: 屬於spring-beans模塊,提供多層次的BeanFactory結構,容許多個BeanFactory之間存在繼承關係。例如在 WebApplicationCpontext 的使用場景中, WebApplicationContext 依賴於基於XML配置的 XMLApplicationContext等;
AutowireCapableBeanFactory
:屬於spring-beans模塊,提供基於bean的自動裝配能力,包括依賴查找(Dependence Lookup)和依賴注入(Dependence Inject)能力;
ConfigurableBeanFactory
: 屬於spring-beans模塊,提供 DefaultListableBeanFactory 相關數據的讀取和配置接口,同時提供銷燬bean 的能力。
ConfigurableListableBeanFactory
在 AutowireCapableBeanFactory
提供了部分依賴的設置能力,例如,註冊特定類型的依賴默認值( registerResolvableDependency(Class<?> dependencyType, Object autowiredValue)
),判斷某個bean依賴關係是否存在候選集合(boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
),依賴忽略特定的接口或者類型的依賴注入(ignoreDependencyType(Class<?> type)
、void ignoreDependencyInterface(Class<?> ifc)
)。依賴候選集的查詢須要容器提供基於類型查詢對應的bean的能力,所以接口ConfigurableListableBeanFactory
繼承了接口ListableBeanFactory
,所以,在實現的全部接口中, ConfigurationListableBeanFactory
的繼承關係是最爲複雜的,聚合了不少抽象的能力,是最接近實現類 DefaultListableBeanFactory
的接口,所以在spring 在對外提供BeanFactory預處理接口BeanFactoryPostProcessor
的時候,對應的方法簽名是 void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
,而不是~~void postProcessBeanFactory(BeanFactory beanFactory)
~~,這樣也能夠避免BeanFactoryPostProcessor#postProcessBeanFactory
中傳入的參數是ApplicationContext。
接口BeanDefinitionRegistry
提供了基於beanName的 BeanDefinition 的註冊、刪除和查詢能力。
DefaultListableBeanFactory
的類繼承關係DefaultListableBeanFactory
的類繼承關係,自上到下依次對應的是 Object <- SimpleAliasRegistry <- DefaultSingletonBeanRegistry <- FactoryBeanRegistrySupport <- AbstractBeanFactory <- AbstractAutowireCapableBeanFactory <- DefaultListableBeanFactory 。
從上到下,BeanFactory 關注點變得愈來愈具體,邏輯也變得愈來愈複雜,對應的能力逐漸強大:從最初的別名註冊能力,到bean對象的註冊管理和FactoryBean
對象的管理,再到BeanFactory配置管理,自動裝配能力的實現,最後纔是BeanDefination註冊管理,支持根據BeanDefination進行對象的實例化。
BeanFactory
vs FactoryBean
FactoryBean
當你向容器註冊名字爲 factoryBeanName 的 FactoryBean的時候,你向容器註冊的是 名字爲&factoryBeanName的FactoryBean的對象,,經過factoryBeanName獲取到的是 FactoryBean#getObject
返回的對象,該對象不受Spring 容器管理,具體參考What's a FactoryBean?。FactoryBean
簡化一部分實例過程,減小無關Bean的註冊。例如 AbstractEntityManagerFactoryBean
相關實現。@Configuration
public class FactoryBeanDemo {
public static final String beanName = "user";
@Bean(beanName)
public FactoryBean<User> factoryBean() {
return new FactoryBean<User>() {
public User getObject() {
User user = new User();
user.setName("mijack");
return user;
}
public Class<?> getObjectType() {
return User.class;
}
};
}
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(FactoryBeanDemo.class);
System.out.println(applicationContext.getBean(beanName) instanceof User);// true
System.out.println(applicationContext.getBean(beanName) instanceof FactoryBean); // false
System.out.println(applicationContext.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName) instanceof User);//false
System.out.println(applicationContext.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName) instanceof FactoryBean);//true
System.out.println(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, User.class));// [user]
}
}
複製代碼
從 ApplicationContext
繼承的接口上看,接口 ApplicationContext
繼承了接口 ListableBeanFactory
、 HierarchicalBeanFactory
、 EnvironmentCapable
、MessageSource
、 ApplicationEventPublisher
、 ResourcePatternResolver
,提供IoC容器能力、環境管理、事件發佈機制、事件發佈-響應機制、資源定位加載、i18n的能力。
從 ApplicationContext
實現的子類上看,ApplicationContext根據不用應用場景分紅不一樣的實現類:
圖中中藍框部分經過 ApplicationContext
-> ConfigurableApplicationContext
-> AbstractApplicationContext
-> AbstractRefreshableApplicationContext
-> AbstractRefreshableConfigApplicationContext
-> AbstractRefreshableWebApplicationContext
& AbstractXmlApplicationContext
的繼承體系實現了相關功能,可是這樣存在必定問題:不一樣場景下,我文件加載的方式都要從新實現一遍,例如實現XML的配置加載,須要分紅文件系統和Web應用兩種不一樣的實現類,代碼複用度過低。
爲了不上述狀況,進一步提升代碼的利用率,Spring 提出 GenericApplicationContext
類繼承體系(紅色框的實現體系): GenericApplicationContext
實現了接口 BeanDefinitionRegistry
,將資源註冊過程從核心流程中剝離出來,特定場景下數據加載解析,有子類實現,提供友好的API接口。不一樣於 AbstractRefreshableApplicationContext
(維護內部的 BeanFactory
,支持刷新時從新建立 BeanFactory ), GenericApplicationContext
中的 beanFactory 支持從外界導入,爲了不復雜的狀態管理, GenericApplicationContext
默認不支持容器的從新刷新。