文章目錄
Spring的擴展功能
Spring的核心就是BeanFactory,在原生的BeanFactory實現->XmlBeanFactory中,最小化的創建了一個BeanFactory,但是我們在Spring框架中使用的往往不是這個BeanFactory的實現.
ApplicationContext
通過查看這個繼承樹我們不難看出,在Spring2.0-Reactive的實現也是繼承了ApplicationContext
上面這段代碼來自SpringBoot的main函數,我們可以發現,refresh就是在這個地方調用的,Spring的整個留着也是從這裏開始加載的
@Override
public final void refresh() throws BeansException, IllegalStateException {
try {
super.refresh();
}
catch (RuntimeException ex) {
stopAndReleaseReactiveWebServer();
throw ex;
}
}
跟進去之後可以看到實際上是調用了AbstractApplicationContext的方法.
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 這裏實現了一個空函數方便我們擴展
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
這裏就是Spring 初始化的整個流程,獲取到beanFactory之後就是開始對Spring功能的擴展,在這些擴展裏給開發者流出了很多可擴展的切面,根據這裏的,比如BeanFactoryPostProcess.
強調一下,Spring的擴展功能有很多,這裏我只記錄自己遇到的和使用過的
添加ApplicationContextAwareProcess處理器
該處理器會掃描我們的Bean如果屬於Aware會將我們需要的對象set進去.
實際上ApplicationContextAwareProcess實現了BeanPostProcess
對於實現了BeanPostProcess的方法我們只需要關心他的兩個方法:
- postProcessBeforeInitialization
- postProcessAfterInitialization
這裏簡單介紹下BeanPostProcess是如何實現的:
這段代碼的出處是創建Bean的時候,其內部會允許子類去實例化一個bean,所以這裏會判斷如果返回的bean不爲空則直接跳出將bean返回
直接進入AwareProcess的前置處理器
這裏可以看出如果我們的bean繼承了這幾個方法就會在這裏將實現完成
由於我們的調用在BeanFactoryProcess中已經完成了,所以需要在接下來的實例化過程中將這些類忽略掉
該擴展爲硬編碼的形式存在,所以這個擴展點主要是給我們提供一些幫助(在創建bean的時候),這些參數的獲取是通過實現傳遞的,所以需要在實例化bean的時候將他們忽略掉.
FactoryBean的使用
通過xml的方式實現過於複雜,使用FactoryBean來實現接口,通過實現FactoryBean來實現該接口定製化實例化的bean邏輯.
通過調用getObject()方法來實現Bean的實例化
BeanFactory的後處理
BeanFactory作爲Spring容器功能的基礎,存放着所有已加載的bean.我們在真正實例化bean之前可以在這裏對其進行擴展.
調用BeanFactoryPostProcess
調用BeanFactoryPostProcess是Spring通過硬編碼的形式放在初始化流程中的,通過觀察我們可以發現
下面這段代碼邏輯出自invokeBeanFactoryPostProcessors(),這裏就是調用BeanFactoryPostProcessors的地方,觀看下面這個循環判斷可以瞭解到爲什BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry會優先調用.
所有的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor都放在下面的這兩個緩存中等待調用.
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
註冊BeanPostProcessor
註冊BeanPostProcessor的邏輯和上面的類似,對其進行一系列的校驗之後將其存儲到BeanFactory的緩存中
調用順序
這裏強調一下BeanFactoryPostProcessor和BeanDefinitionRegistry以及BeanPostProcessor的調用順序
BeanDefinitionRegistry
BeanDefinitionRegistry是最先調用的,調用的位置在上文已經給出,是初始化BeanFactoryPostProcessor的時候進行調用,而且調用的時候沒有先後順序,只是對BeanFactoryPostProcessor本身進行加工
聲明瞭幾個就調用幾次
BeanFactoryPostProcessor
BeanFactoryPostProcessor的調用位置會有以下之中:
- 按順序調用
- 無需調用
首先調用排序好的BeanFactoryPostProcessor,在調用沒有排序的BeanFactoryPostProcessor
聲明瞭幾個就調用幾次
BeanFactoryPostProcessor
BeanFactoryPostProcessor這個方法的調用位置根據Bean的實例化決定,在Bean的實例化前後會調用其中的兩個方法
所有的Bean在實例化的時候都會調用
初始化ApplicationEventMulticaster
ApplicationEventMulticaster的初始化過程比較簡單,這裏在默認的情況下會註冊一個Spring默認的管理器,如果用戶自己指定也可以由用戶注入.
這段代碼的源碼內容也比較簡單直觀,這裏把他的多播器列出來
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
這裏會將所有的時間廣播到所有的監聽器上,如果有異步執行器則會使用異步處理.
註冊監聽器
這裏顧名思義,就是將我們的listener註冊到監聽器上,簡而言之就是add()到緩存的List中.
初始化非延遲加載單例
在這裏會將所有的非延遲單例完成加載,這麼做是一件好事,因爲我們的bean錯誤可以及時發現.
finishRefresh
Spring的開啓和結束事件就是在這裏發出的,通過ApplicationEventMulticaster來發布Spring的各種狀態.