Spring Ioc原始碼分析系列--Ioc容器注冊BeanPostProcessor后置處理器以及事件訊息處理
前言
上一篇分析了BeanFactoryPostProcessor的作用,那么這一篇繼續在refresh()方法里游蕩,相信對Spring熟悉點的朋友,在看完BeanFactoryPostProcessor后,一定會想到Spring里面還有個BeanPostProcessor,那這個東西是什么作用呢?下面會進行介紹,同時由于注冊BeanPostProcessor的邏輯比較簡單,這里會穿插一下BeanPostProcessor生效的時機和原始碼邏輯,實際上這部分應該是Bean實體化出現的邏輯,
介紹完這部分之后,會介紹Spring的訊息源初始化、廣播器的初始以及監聽器的初始化,這部分作業完成之后,Spring容器就會進入到Bean的創建程序,因為準備作業已經做得差不多了,容器已經準備好,接下來就是初始化Bean放進去容器里面,
BeanFactoryPostProcessor和BeanPostProcessor之間的區別
這兩個的區別還是很顯而易見的,主要表現在應用的階段不同,BeanFactoryPostProcessor是對BeanDefinition直接生效的,這更加底層,也更加原始,所以直接使用BeanFactoryPostProcessor會比較少,BeanPostProcessor是對bean實體生效的,相對于對BeanDefinition的處理,這個階段更加靠后,BeanFactoryPostProcessor階段bean是尚未初始化出來的,BeanPostProcessor處理的時候已經生成了實體物件,BeanPostProcessor會在物件的實體基礎上進行一個更進一步的加工,
不熟悉的朋友看起來可能有點抽象,那么這里舉一個例子吧,
BeanFactoryPostProcessor的類比:
假設你要造一個杯子,那么杯子需要一份原材料串列,材質你可以選擇鐵、銅、金、銀等等,樣式你可以選擇圓型、方形、橢圓等等,假設開始原料選擇鐵,形狀為圓形,那么這一份原料串列對應的就是一個BeanDefinition,原料串列出來后,沒什么問題就會按照這一份串列去創建一個杯子,但是有時候需要一些額外的操作,例如對某些BeanDefinition進行檢查,假設有一個檢查員BeanFactoryPostProcessor去檢查每個BeanDefinition,他看到杯子的材質是鐵,覺得有失身份,于是把材料改成了金子,于是后續再去創建杯子的時候,就是個金杯了,
BeanPostProcessor的類比:
BeanPostProcessor的處理階段則要靠后,在上面杯子創建完成之后,才到了BeanPostProcessor出場,BeanPostProcessor會在實體的基礎上進行一些加工,拿杯子來舉例,上一個階段拿到的是一個粗糙的杯子,這里會進行一些處理,例如給杯子加點花紋樣式,給杯子拋光等等,**注意這些操作都是在一個已有的杯子上進行的,但是請注意,這不是絕對的,**BeanPostProcessor除了能對Bean進行深加工外,還能直接進行Bean替換,類比來說,就是換了個杯子,偷梁換柱,Spring Aop的功能就是這樣實作的,把經過代理的Bean放了進去,替換了原有的Bean,
所以比較一下得出一個很明顯的結論:
-
BeanFactoryPostProcessor對BeanDefinition生效
-
BeanPostProcessor對bean實體生效
原始碼分析
registerBeanPostProcessors(beanFactory)
話不多說,下面繼續分析refresh()方法里面的子方法,上一篇分析到了第五個子方法,那這篇從第六個registerBeanPostProcessors(beanFactory)開始,
跟進代碼,可以看到實作都委托給了PostProcessorRegistrationDelegate#registerBeanPostProcessors(beanFactory, this)方法,
/**
* Instantiate and register all BeanPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before any instantiation of application beans.
*
* 實體化并注冊所有 BeanPostProcessor bean,如果給定順序,則按照順序排序,
* <p>必須在應用程式 bean 的任何實體化之前呼叫,
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
繼續跟進,這個方法的邏輯也是比較簡單的,跟上篇的BeanFactoryPostProcessor注冊類似,這里也會按照優先級去對BeanPostProcessor進行排序然后按順序進行注冊,都是些家常套路了,可以跟著注釋去看一下,值得注意的是,這里會額外加入兩個BeanPostProcessor,分別為BeanPostProcessorChecker和ApplicationListenerDetector,BeanPostProcessorChecker主要是用來記錄一些日志,ApplicationListenerDetector是用來檢測實作了ApplicationListener但是getBeanNamesForType()沒探測出來的漏網之魚,這里的漏網之魚可能是一些動態注冊的bean或者一些內部類,這里再次獲取后會放入到applicationListeners集合里,
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 獲取容器中所有的 BeanPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
// 注冊 BeanPostProcessorChecker,當 bean 不符合所有 BeanPostProcessor 處理的條件時,它會在 BeanPostProcessor 實體化期間創建 bean 時記錄一條資訊訊息
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 按照順序分類區分 BeanPostProcessor
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
// 首先注冊實作了 PriorityOrdered 介面的 BeanPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
// 其次注冊實作了 Ordered 介面的 BeanPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
// 現在到了注冊沒有實作上述介面的 BeanPostProcessor
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
// 最后,重新注冊所有內部 BeanPostProcessor MergedBeanDefinitionPostProcessor,
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
// 重新注冊用于將內部 bean 檢測為 ApplicationListeners 的后處理器,將其移動到處理器鏈的末尾(用于拾取代理等),
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
initMessageSource()
接下來繼續進行下一步的準備作業,初始化訊息源,這里是默認使用了父類的訊息源,如果沒有就初始化一個DelegatingMessageSource,這個DelegatingMessageSource會默認將所有的呼叫都委派到父容器的訊息源去決議,如果沒有父容器的訊息源,那么它不會決議任何訊息,
/**
* Initialize the MessageSource.
* Use parent's if none defined in this context.
* 初始化訊息源,如果沒有在此背景關系中定義,則使用父容器的,
*/
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 回傳當前容器職工是否存在 messageSource,忽略祖先容器
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
// 如果存在祖先,并且 messageSource 型別是 HierarchicalMessageSource,則獲取祖先的 messageSource 設定到當前 messageSource 里,
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
// 本地不存在 messageSource,使用空 MessageSource 能夠接受 getMessage 呼叫
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
initApplicationEventMulticaster()
初始化 ApplicationEventMulticaster,如果背景關系中沒有定義,則使用 SimpleApplicationEventMulticaster,
/**
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
*
* 初始化 ApplicationEventMulticaster,
* 如果背景關系中沒有定義,則使用 SimpleApplicationEventMulticaster,
*
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 如果本地容器里存在 applicationEventMulticaster,直接使用本地容器里的 applicationEventMulticaster
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 否則使用 SimpleApplicationEventMulticaster 廣播器
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
// 將給定的單例物件添加到該工廠的單例快取中
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
這個事件廣播器是干什么的呢?其實很簡單,就是把一個事件廣播到所有的ApplicationListener上,可以看一下里面的關鍵方法SimpleApplicationEventMulticaster#multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType),這里就是獲取所有的listener,如果有異步執行緒池,則異步執行,否則逐個呼叫,
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
// 決議事件的型別,這個type會用于后續的 ListenerCacheKey 快取 key 構建
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 獲取執行緒池
Executor executor = getTaskExecutor();
// 逐個廣播事件到 listener,就是將 listener 都遍歷呼叫一遍
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
// 錯誤處理器,記錄任務處理期間發生的錯誤
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 將事件傳入listener,完成事件的監聽回呼
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
// ...
}
}
onRefresh()
這是個空方法,交給子類實作,這里可以用來初始化特定背景關系子類中的其他特殊 bean,也是留出來的一個擴展口,
/**
* Template method which can be overridden to add context-specific refresh work.
* Called on initialization of special beans, before instantiation of singletons.
*
* 可以重寫以添加特定于背景關系的重繪作業的模板方法,在單例實體化之前呼叫特殊 bean 的初始化,
*
* <p>This implementation is empty.
* @throws BeansException in case of errors
* @see #refresh()
*/
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
registerListeners()
上一步已經初始化完成了廣播器,那接下來就是檢查偵聽器并注冊它們,
事件可以按照注冊的型別進行區分,可以分為以下三種:
- 通過
addApplicationListener()手動添加進去的 - 容器里實作了ApplicationListener介面的
- 容器啟動早期需要的事件earlyApplicationEvents,早期事件是需要在這里直接發布的
/**
* Add beans that implement ApplicationListener as listeners.
* Doesn't affect other listeners, which can be added without being beans.
*
* 添加實作 ApplicationListener 的 bean作為偵聽器,
* 不影響其他監聽器,可以添加而不是 bean,
*/
protected void registerListeners() {
// Register statically specified listeners first.
// 首先注冊靜態指定的監聽器,也就是通過addApplicationListener(ApplicationListener<?> listener) 注冊的listener,
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// 這里只是獲取beanName,是為了避免初始化 bean 導致后置處理器失效
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
// 逐個注冊listener
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
// 發布早期應用程式事件,因為我們終于有了一個廣播器......
// 忍辱負重,早期事件存到了這里才能進行發布,因為之前沒有廣播器
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
// 逐個發布事件
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
finishBeanFactoryInitialization(beanFactory)
準備作業已經基本完成,接下來就到了finishBeanFactoryInitialization(beanFactory)方法了,從方法名可以看到,這個方法是負責完成此背景關系的 bean 工廠的初始化,初始化所有剩余的單例 bean,可以看到這個方法開始也進行了一些準備作業,例如注冊型別裝換器、占位符處理器以及LoadTimeWeaverAware加載等,最后會呼叫beanFactory.preInstantiateSingletons()進行物件創建,由于這里是比較復雜的程序,會分幾篇文章去詳細分析,這篇文章就是大概從表面上走完refresh()方法的原始碼,
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*
* 完成此背景關系的 bean 工廠的初始化,初始化所有剩余的單例 bean,
*
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 初始化一個ConversionService用于型別轉換,這個ConversionService會在實體化物件的時候用到
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 添加一個StringValueResolver,用于處理占位符,可以看到,默認情況下就是使用環境中的屬性值來替代占位符中的屬性
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 創建所有的LoadTimeWeaverAware
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
// 靜態織入完成后將臨時的類加載器設定為null,所以除了創建LoadTimeWeaverAware時可能會用到臨時類加載器,其余情況下都為空
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 將所有的配置資訊凍結
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 開始進行真正的創建
beanFactory.preInstantiateSingletons();
}
finishRefresh()
到這里容器已經準備好了,bean也已經實體化完成,就差最后的一些事件通知和后續的兜底處理,這里比較重要的是會呼叫到所有實作了LifecycleProcessor#onRefresh()的Bean,在這里可以讓生命周期Bean實作很多擴展,其次比較重要的是會發布一個ContextRefreshedEvent事件,通知所有監聽器容器已經啟動完成,這里就可以實作一些容器啟動完成后的回呼或者是一些任務等,任君發揮,
/**
* Finish the refresh of this context, invoking the LifecycleProcessor's
* onRefresh() method and publishing the
* {@link org.springframework.context.event.ContextRefreshedEvent}.
*
* 完成容器的重繪啟動,呼叫所有 LifecycleProcessor#onRefresh() 方法來發布 ContextRefreshedEvent 事件
*
*/
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
// 清除容器背景關系級別的資源快取(例如ASM掃描的元資料)
clearResourceCaches();
// Initialize lifecycle processor for this context.
// 初始化背景關系的 lifecycle processor
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
// 首先將重繪傳播到生命周期處理器,
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 發布最終事件,
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
// 參與 LiveBeansView MBean(如果處于活動狀態),
LiveBeansView.registerApplicationContext(this);
}
總結
本文的重點有點分散,更像是走馬觀花,但是分散里的重點毫無疑問是理解和區分BeanFactoryPostProcessor和BeanPostProcessor之間的區別,文章開頭通過一個例子去類比了一下這二者的作用階段和分別可以完成什么作業,個人覺得還是比較貼切的,希望能夠幫助到理解,
到這里已經基本把refresh()方法走了一遍,當然這里看到的大部分都是一些基礎準備作業,最關鍵的Bean實體化是還沒有開始分析的,Bean的實體化會后續分好幾篇文章繼續去分析,
今天這篇文章是比較簡單的,沒有太多邏輯,基本上都是一個一個小方法,嵌套不深,因為深入的我都不寫了哈哈,
這系列寫到這里,才完成了準備作業,接下來的Bean創建才是真正開始了重頭戲,那接下來繼續慢慢分析吧,
如果有人看到這里,那在這里老話重提,與君共勉,路漫漫其修遠兮,吾將上下而求索,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/477505.html
標籤:Java
下一篇:JUC部分并發類使用方式
