BeanFactory

DefaultListableBeanFactory簡(jiǎn)單容器
此圖是默認(rèn)容器DefaultListableBeanFactory的繼承實(shí)現(xiàn)關(guān)系圖:
1、BeanFactory接口:容器頂級(jí)接口,提供了容器最基本的能力,包括獲取bean,是否包含bean,是否單例,獲取bean類型,Bean的別名等方法。
2、ListableBeanFactory接口:BeanFactory的子接口;具有批量獲取Bean的能力
3、HierarchicalBeanFactory接口:具有訪問父容器的能力。有層次的BeanFactory。
4、AutowireCapableBeanFactory接口:繼承BeanFactory,擴(kuò)展了自動(dòng)裝配能力。這個(gè)接口更多的作用是用于于與其他框架集成,把不在spring容器中的Bean加入到Spring容器生命周期管理中來。此接口很少用
5、ConfigurableBeanFactory:定義了BeanFactory的配置。繼承HierarchicalBeanFactory和SingletonBeanRegistry接口。實(shí)現(xiàn)了此接口的容器,具有層次,單例BeanDefinition注冊(cè)功能。
6、ConfigurableListableBeanFactory:大融合接口,除了具有上述接口的能外,還具有類加載器、類型轉(zhuǎn)化、屬性編輯器、BeanPostProcessor、作用域、bean定義、處理bean依賴關(guān)系、bean銷毀等功能。
7、SingletonBeanRegistry接口:具有Bean的操作能力,注冊(cè)、查詢、獲取Bean數(shù)量等能力。注意此處的Bean是實(shí)例,區(qū)別于BeanDefinition。
8、SimpleAliasRegistry:Bean的別名操作類,實(shí)現(xiàn)了AliasRegistry,具有存儲(chǔ)Bean別名,注冊(cè)Bean別名,獲取Bean別名的功能,aliasMap屬性存儲(chǔ)Bean別名。
9、DefaultSingletonBeanRegistry:除了繼承了SimpleAliasRegistry的功能外,最重要的是實(shí)現(xiàn)了SingletonBeanRegistry接口,具有存儲(chǔ)Bean實(shí)例、注冊(cè)Bean、獲取Bean的能力。我們定義的被Spring管理的Class類的實(shí)例對(duì)象,以及實(shí)例的之間的相互依賴關(guān)系都是存儲(chǔ)在此類中,默認(rèn)常用的容器DefaultListableBeanFactory的Bean的相關(guān)能力,就是通過間接繼承此類來實(shí)現(xiàn)的。
/** Disposable bean instances: bean name to disposable instance. */
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
/** Map between dependent bean names: bean name to Set of dependent bean names. */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
10、FactoryBeanRegistrySupport:提供多工廠Bean的支持,F(xiàn)actoryBean通過其名字我也可以看出是生產(chǎn)Bean的Bean。
11、AbstractBeanFactory抽象類:承上啟下,從圖中我們看出AbstractBeanFactory通過繼承關(guān)系繼承FactoryBeanRegistrySupport各種能力,而且實(shí)現(xiàn)了右邊部分接口,已然是比較完備的Bean容器了。AbstractBeanFactory還通過模板模式定義了獲取Bean的算法骨架。
12、AbstractAutowireCapableBeanFactory:具有大部分的能力,實(shí)現(xiàn)了AbstractBeanFactory定義的模板方法,其中doCreateBean方法邏輯是把一個(gè)BeanDefinition變成Bean的過程,這個(gè)方法非常重要。通常我們使用類創(chuàng)建對(duì)象,直接new出來,spring把BeanDefinition到Bean的過程模板化,留下了很多擴(kuò)展點(diǎn),留給使用者可以在不同的時(shí)刻自定義BeanDefition創(chuàng)建Bean的過程。
13、DefaultListableBeanFactory常用的默認(rèn)容器實(shí)現(xiàn),也是spring最常使用的容器類。DefaultListableBeanFactory實(shí)現(xiàn)了BeanDefinitionRegistry接口,說明DefaultListableBeanFactory具有存儲(chǔ)BeanDefinition、操作BeanDefinition的能力,DefaultListableBeanFactory通過繼承關(guān)系也具有了Bean的存儲(chǔ)操作功能。
小結(jié):
- 1、BeanFactory體系,接口分明,完美的體現(xiàn)了接口分離原則。
- 2、BeanFactory體系中有兩種存儲(chǔ):一種是BeanDefinition的存儲(chǔ),另一個(gè)是Bean的存儲(chǔ)。
- 3、DefaultListableBeanFactory作為最常用的容器類,不但具有BeanDefinition的存儲(chǔ)操作功能,而且通過繼承具有Bean的存儲(chǔ)操作功能的DefaultListableBeanFactory把存儲(chǔ)的BeanDefinition通過一定算法創(chuàng)建Bean并存儲(chǔ)起來。
BeanDefinition、BeanFactory、Bean三者關(guān)系
通過上面的對(duì)各個(gè)接口、類的認(rèn)識(shí),我們?cè)賮砜纯慈叩年P(guān)系。
我們向BeanFactory容器中注入一個(gè)BeanDefinition。BeanFactory幫我們存儲(chǔ)起來。當(dāng)我們想要得到一個(gè)Bean時(shí),BeanFactory 幫我們把BeanDefinition創(chuàng)建成Bean并緩存起來,這個(gè)創(chuàng)建過程是可參與的。
- BeanFactory保存了BeanDefiniton與Bean。
- BeanFactory具有使用BeanDefinition創(chuàng)建Bean的功能。
- BeanFactory允許使用者可以干預(yù)BeanDefinition生成Bean的功能。
BeanFactory中的擴(kuò)展點(diǎn)
設(shè)計(jì)原則之開閉原則說的特別好:說一個(gè)軟件實(shí)體應(yīng)該通過擴(kuò)展來實(shí)現(xiàn)變化。
很多優(yōu)秀的框架都有類似的擴(kuò)展點(diǎn)設(shè)計(jì),列如:
- Tomcat中的Filter
- Tomcat中的pipline-valve
- springmvc中的Interceptor
BeanFactory中從BeanDefinition到Bean并不是一下子就完成的,這有一個(gè)過程。spring正是在這個(gè)過程中留下擴(kuò)展點(diǎn)來實(shí)現(xiàn)BeanDefinition到Bean的過程中的各種自定義變化。
從上面我們得知:AbstractAutowireCapableBeanFactory中有個(gè)doCreateBean()正是BeanDefinition到Bean的創(chuàng)建方法,接下來我們看看這個(gè)方法有哪些擴(kuò)展點(diǎn):
- 1、xxxAware接口:使Bean可以獲得xxx。列如實(shí)現(xiàn)了BeanFactoryAware接口的類,可以在該Bean被加載的過程中獲取加載該Bean的BeanFactory。
- 2、BeanPostProcessor:BeanPostProcessor接口定義的兩個(gè)方法,分別在bean的初始化方法(InitializingBean接口,或者init-method定義)執(zhí)行的前后執(zhí)行
- 3、InitializingBean接口:實(shí)現(xiàn)了InitializingBean接口的類,執(zhí)行afterPropertiesSet
- 4、自定義的init-method方法。
ApplicationContext高級(jí)容器
容器分為兩套體系:一套是早期的 BeanFactory 體系;還有一套是現(xiàn)在常用的ApplicationContext,也可稱為應(yīng)用上下文,它繼承了 BeanFactory,它除了有 BeanFactory 的功能外,還提供了其他服務(wù),例如事務(wù)和 AOP 服務(wù)、國(guó)際化(il8n)的消息源以及應(yīng)用程序事件處理等企業(yè)級(jí)的服務(wù)。
Spring支持兩種配置方式,在早期都是 XML 配置文件的方式,而現(xiàn)在使用的是注解配置的方式。BeanFactory體系的容器一般用來處理 XML配置文件的方式,而ApplicationContext 體系則都可以處理。
ApplicationContext 是 BeanFactory 子類,它不僅包含 BeanFactory 所有功能,還對(duì)其進(jìn)行了擴(kuò)展,而我們習(xí)慣將 ApplicationContext 稱為應(yīng)用上下文,因?yàn)槿萜髦皇撬幕竟δ堋?/p>

傳統(tǒng)的基于XML配置的經(jīng)典容器:
- FileSystemXmlApplicationContext:從文件系統(tǒng)加載配置
- ClassPathXmlApplicationContext:從ClassPath加載配置
- XmlWebApplicationContext:用于Web應(yīng)用程序的容器
目前比較流行的基于注解的容器:
- AnnotationConfigServletWebServerApplicationContext:該類在SpringBoot的boot模塊中
- AnnotationConfigReactiveWebServerApplicationContext:滿足響應(yīng)式的容器需求,該類在SpringBoot的boot模塊中。
- AnnotationConfigApplicationContext:普通的非Web應(yīng)用使用該容器
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
// 返回此應(yīng)用程序上下文的唯一ID
@Nullable
String getId();
// 返回此上下文所屬的應(yīng)用程序名稱
String getApplicationName();
// 返回應(yīng)用上下文具像化的類名
String getDisplayName();
// 返回第一次加載此上下文時(shí)的時(shí)間戳
long getStartupDate();
// 獲取父級(jí)應(yīng)用上下文
@Nullable
ApplicationContext getParent();
// 將 AutowireCapableBeanFactory 接口暴露給外部使用
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
ApplicationContext 自身提供的方法非常簡(jiǎn)單,但它繼承了六個(gè)接口,來擴(kuò)展自身功能:
- EnvironmentCapable:獲取 Environment。
- ListableBeanFactory、HierarchicalBeanFactory:這是 BeanFactory 體系接口,分別提供 Bean 迭代和訪問父容器的功能。
- MessageSource:支持國(guó)際化功能。
- ApplicationEventPublisher:應(yīng)用事件發(fā)布器,封裝事件發(fā)布功能的接口。
- ResourcePatternResolver:該接口繼承至 ResourceLoader ,作用是加載多個(gè) Resource。
ApplicationContext 同樣提供了非常多的實(shí)現(xiàn)類,其又可細(xì)分為兩大類, ConfigurableApplicationContext 和 WebApplicationContext。
ConfigurableApplicationContext
該接口是比較重要的一個(gè)接口,幾乎所有的應(yīng)用上下文都實(shí)現(xiàn)了該接口。該接口在ApplicationContext的基礎(chǔ)上提供了配置應(yīng)用上下文的能力,此外提供了生命周期的控制能力。
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
// 應(yīng)用上下文配置時(shí),這些符號(hào)用于分割多個(gè)配置路徑
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
// BeanFactory中,ConversionService類所對(duì)應(yīng)的bean的名字。如果沒有此類的實(shí)例的話嗎,則使用默認(rèn)的轉(zhuǎn)換規(guī)則
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
//LoadTimeWaver類所對(duì)應(yīng)的Bean在容器中的名字。如果提供了該實(shí)例,上下文會(huì)使用臨時(shí)的 ClassLoader ,這樣,LoadTimeWaver就可以使用bean確切的類型了
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
// Environment 類在容器中實(shí)例的名字
String ENVIRONMENT_BEAN_NAME = "environment";
// System 系統(tǒng)變量在容器中對(duì)應(yīng)的Bean的名字
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
// System 環(huán)境變量在容器中對(duì)應(yīng)的Bean的名字
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
// 設(shè)置容器的唯一ID
void setId(String id);
// 設(shè)置此容器的父容器
void setParent(@Nullable ApplicationContext parent);
// 設(shè)置容器的 Environment 變量
void setEnvironment(ConfigurableEnvironment environment);
// 以 ConfigurableEnvironment 的形式返回此容器的環(huán)境變量。以使用戶更好的進(jìn)行配置
@Override
ConfigurableEnvironment getEnvironment();
// 此方法一般在讀取應(yīng)用上下文配置的時(shí)候調(diào)用,用以向此容器中增加BeanFactoryPostProcessor。增加的Processor會(huì)在容器refresh的時(shí)候使用。
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
// 向容器增加一個(gè) ApplicationListener,增加的 Listener 用于發(fā)布上下文事件,如 refresh 和 shutdown 等
void addApplicationListener(ApplicationListener<?> listener);
// 向容器中注入給定的 Protocol resolver
void addProtocolResolver(ProtocolResolver resolver);
// 這是初始化方法,因此如果調(diào)用此方法失敗的情況下,要將其已經(jīng)創(chuàng)建的 Bean 銷毀。
// 換句話說,調(diào)用此方法以后,要么所有的Bean都實(shí)例化好了,要么就一個(gè)都沒有實(shí)例化
void refresh() throws BeansException, IllegalStateException;
// 向JVM注冊(cè)一個(gè)回調(diào)函數(shù),用以在JVM關(guān)閉時(shí),銷毀此應(yīng)用上下文
void registerShutdownHook();
// 關(guān)閉此應(yīng)用上下文,釋放其所占有的所有資源和鎖。并銷毀其所有創(chuàng)建好的 singleton Beans
@Override
void close();
// 檢測(cè)此 FactoryBean 是否被啟動(dòng)過
boolean isActive();
// 返回此應(yīng)用上下文的容器。
// 千萬(wàn)不要使用此方法來對(duì) BeanFactory 生成的 Bean 做后置處理,因?yàn)閱卫?Bean 在此之前已經(jīng)生成。
// 這種情況下應(yīng)該使用 BeanFactoryPostProcessor 來在 Bean 生成之前對(duì)其進(jìn)行處理
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}
該接口下又有幾個(gè)重要的實(shí)現(xiàn)類:
- AbstractApplicationContext:這是個(gè)抽象類,僅實(shí)現(xiàn)了公共的上下文特性。這個(gè)抽象類使用了模板方法設(shè)計(jì)模式,需要具體的實(shí)現(xiàn)類去實(shí)現(xiàn)這些抽象的方法。
- GenericApplicationContext:該類繼承自 AbstractApplicationContext,是為通用目的設(shè)計(jì)的,它能加載各種配置文件,例如 xml,properties 等等。它的內(nèi)部持有一個(gè) DefaultListableBeanFactory 的實(shí)例,實(shí)現(xiàn)了 BeanDefinitionRegistry 接口,以便允許向其應(yīng)用任何 bean 的定義的讀取器。
- AnnotationConfigApplicationContext:該類繼承自 GenericApplicationContext ,提供了注解配置(例如:@Configuration、@Component等)和類路徑掃描(scan方法)的支持。
WebApplicationContext
該接口是專門為 Web 應(yīng)用準(zhǔn)備的,其允許從相對(duì)于 Web 根目錄的路徑中裝載配置文件完成初始化。
public interface WebApplicationContext extends ApplicationContext {
// 整個(gè) Web 應(yīng)用上下文是作為屬性放置在 ServletContext 中的,該常量就是應(yīng)用上下文在 ServletContext 屬性列表中的 key
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
// 定義了三個(gè)作用域的名稱
String SCOPE_REQUEST = "request";
String SCOPE_SESSION = "session";
String SCOPE_APPLICATION = "application";
// 在工廠中的 bean 名稱
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
// ServletContext 初始化參數(shù)名稱
String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
// 在工廠中 ServletContext 屬性值環(huán)境bean的名稱
String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";
// 用來獲取 ServletContext 對(duì)象
@Nullable
ServletContext getServletContext();
}
該接口的核心實(shí)現(xiàn)類有:
- ConfigurableWebApplicationContext:該接口同時(shí)繼承了 WebApplicationContext 和 ConfigurableApplicationContext,提供了 Web 應(yīng)用上下文的可配置的能力。
- GenericWebApplicationContext:該類繼承自 GenericApplicationContext,實(shí)現(xiàn)了 ConfigurableWebApplicationContext。
- XmlWebApplicationContext:該上下文是使用 Xml 配置文件的方式,不過是在 Web 環(huán)境中使用的。
- AnnotationConfigServletWebServerApplicationContext:該類是被 SpringBoot 擴(kuò)展而來的,SpringBoot 使用的就是該上下文。
差異對(duì)比
從上面可以看出 BeanFactory 是 Sping 框架的基礎(chǔ)接口,一般是面向 Spring 本身;而 ApplicationContext 是以 BeanFactory 為基礎(chǔ)進(jìn)行綜合能力擴(kuò)展,用于滿足大型業(yè)務(wù)應(yīng)用的創(chuàng)建, ApplicationContext 一般面向使用 Sping 框架的開發(fā)者。幾乎所有的應(yīng)用場(chǎng)合我們都是直接使用 ApplicationContet 而非底層的 BeanFactory。
下表列出了BeanFactory 和 ApplicationContext 接口和實(shí)現(xiàn)所提供的功能:
| 功能 / 特點(diǎn) | BeanFactory | ApplicationContext |
|---|---|---|
| Bean 實(shí)例化/裝配 | 有 | 有 |
| BeanPostProcessor 自動(dòng)注冊(cè) | 沒有 | 有 |
| BeanFactoryPostProcessor 自動(dòng)注冊(cè) | 沒有 | 有 |
| MessageSource 便捷訪問(針對(duì)i18n) | 沒有 | 有 |
| ApplicationEvent 發(fā)布 | 沒有 | 有 |