一、refresh 方法之 registerBeanPostProcessors
下面我們來分析這個注冊 Bean 的後置處理器方法,這裡僅僅隻是注冊,調用階段則是在 Bean 進行執行個體化的時候調用。
方法入口
registerBeanPostProcessors(beanFactory);
進入
org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 1.注冊BeanPostProcessor
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
再進入會來到真正注冊的方法
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors
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.
// 擷取 BeanPostProcessor 類型數量
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
// 添加BeanPostProcessorChecker(主要用于記錄資訊)到beanFactory中
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 定義不同的變量用于區分: 實作PriorityOrdered接口的BeanPostProcessor、實作Ordered接口的BeanPostProcessor、普通BeanPostProcessor
// priorityOrderedPostProcessors: 用于存放實作PriorityOrdered接口的BeanPostProcessor
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// internalPostProcessors: 用于存放Spring内部的BeanPostProcessor
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
// orderedPostProcessorNames: 用于存放實作Ordered接口的BeanPostProcessor的beanName
List<String> orderedPostProcessorNames = new ArrayList<>();
// nonOrderedPostProcessorNames: 用于存放普通BeanPostProcessor的beanName
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 周遊postProcessorNames, 将 BeanPostProcessors 按類型區分開
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 如果ppName對應的Bean執行個體實作了PriorityOrdered接口, 則拿到ppName對應的Bean執行個體并添加到priorityOrderedPostProcessors
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
// 如果ppName對應的Bean執行個體也實作了MergedBeanDefinitionPostProcessor接口,
// 則将ppName對應的Bean執行個體添加到internalPostProcessors
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 如果ppName對應的Bean執行個體沒有實作PriorityOrdered接口, 但是實作了Ordered接口, 則将ppName添加到orderedPostProcessorNames
orderedPostProcessorNames.add(ppName);
}
else {
// 否則, 将ppName添加到nonOrderedPostProcessorNames
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
// 首先, 注冊實作PriorityOrdered接口的BeanPostProcessors
// 對priorityOrderedPostProcessors進行排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 注冊priorityOrderedPostProcessors
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
// 接下來, 注冊實作Ordered接口的BeanPostProcessors
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
// 拿到ppName對應的BeanPostProcessor執行個體對象
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
// 将ppName對應的BeanPostProcessor執行個體對象添加到orderedPostProcessors, 準備執行注冊
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
// 如果ppName對應的Bean執行個體也實作了MergedBeanDefinitionPostProcessor接口,
// 則将ppName對應的Bean執行個體添加到internalPostProcessors
internalPostProcessors.add(pp);
}
}
// 對orderedPostProcessors進行排序
sortPostProcessors(orderedPostProcessors, beanFactory);
// 注冊orderedPostProcessors
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
// 注冊所有正常的BeanPostProcessors
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
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.
// 最後, 重新注冊所有内部BeanPostProcessors(相當于内部的BeanPostProcessor會被移到處理器鍊的末尾)
sortPostProcessors(internalPostProcessors, beanFactory);
// 注冊internalPostProcessors
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).
// 重新注冊ApplicationListenerDetector( 主要是為了移動到處理器鍊的末尾)
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
這個方法和 invokeBeanFactoryPostProcessors 方法的流程有點類似,先找到所有符合類型的類,然後按照不同類型進行處理,那對應上面的源碼還是來總結一下幹了些啥。
- 擷取所有的實作 BeanPostProcessor 接口的類
- 記錄擷取到的 BeanPostProcessor 數量,并添加了一個用于記錄資訊的後置處理器
- 建立存放不同類型的集合,用于區分擷取到的 BeanPostProcessor 類
- 先注冊實作 PriorityOrdered接口的 BeanPostProcessor,并且判斷是否還實作了 MergedBeanDefinitionPostProcessor,如果是則存放 internalPostProcessors 集合中
- 後注冊實作了 Ordered 接口的 BeanPostProcessor,并且判斷是否還實作了 MergedBeanDefinitionPostProcessor,如果是則存放 internalPostProcessors 集合中
- 接着注冊普通的 BeanPostProcessor,并且判斷是否還實作了 MergedBeanDefinitionPostProcessor,如果是則存放 internalPostProcessors 集合中
- 最後注冊 internalPostProcessors 集合中的 BeanPostProcessor 。
以上流程很好了解,不是很難,那我們接着來看看 BeanPostProcessor 是如何注冊的吧,也即 registerBeanPostProcessors 方法。
方法源碼
org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
// 周遊傳入的後置處理器集合,依次放入 BeanFactory 中
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
在進入 addBeanPostProcessor 方法
org.springframework.beans.factory.support.AbstractBeanFactory#addBeanPostProcessor
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// 如果beanPostProcessor已經存在則移除(可以起到排序的效果,beanPostProcessor可能本來在前面,移除再添加,則變到最後面)
this.beanPostProcessors.remove(beanPostProcessor);
// 将beanPostProcessor添加到beanPostProcessors中
this.beanPostProcessors.add(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
// 如果beanPostProcessor是InstantiationAwareBeanPostProcessor, 則将hasInstantiationAwareBeanPostProcessors設定為true,
// 該變量用于訓示beanFactory是否已注冊過InstantiationAwareBeanPostProcessors
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
// 如果beanPostProcessor是DestructionAwareBeanPostProcessor, 則将hasInstantiationAwareBeanPostProcessors設定為true,
// 該變量用于訓示beanFactory是否已注冊過DestructionAwareBeanPostProcessor
this.hasDestructionAwareBeanPostProcessors = true;
}
}
方法很簡單,就是向 beanPostProcessors 屬性添加值,并做一些額外處理。
二、refresh 方法之 initMessageSource
這個方法比較簡單,主要作用就是初始化國際化檔案。
那我們先來看案例:
1、配置兩個檔案
2、編寫配置類
@Configuration
public class LifeConfiguration {
// Bean 的名稱必須要是 messageSource
@Bean(name = "messageSource")
public MessageSource getMessageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setDefaultEncoding("UTF-8");
messageSource.addBasenames("message", "message_en");
return messageSource;
}
}
3、測試
public class LifeMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeConfiguration.class);
MessageSource messageSource = applicationContext.getBean(MessageSource.class);
String zhMessage = messageSource.getMessage("user.name", null, null, Locale.CHINA);
String enMessage = messageSource.getMessage("user.name", null, null, Locale.ENGLISH);
System.out.println("zhMessage = " + zhMessage);
System.out.println("enMessage = " + enMessage);
}
}
ok,現在知道使用了,那我們進入正題,源碼分析。
切入口
initMessageSource();
org.springframework.context.support.AbstractApplicationContext#initMessageSource
protected void initMessageSource() {
// 擷取 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 判斷beanFactory中是否有名字為messageSource的bean
// MESSAGE_SOURCE_BEAN_NAME = "messageSource";
// 如果沒有,建立DelegatingMessageSource類作為messageSource的Bean。
// 如果有,從beanFactory中擷取
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
// 從容器中擷取 BeanName 為 messageSource 類型為 MessageSource 的 Bean 執行個體, 并将其指派給目前容器内部的 MessageSource
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
// 判斷父類是否不為空 && 目前對象的 messageSource 是 HierarchicalMessageSource 的執行個體
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.
// 将 HierarchicalMessageSource 的父 MessageSource 指派為 getInternalParentMessageSource()
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
// 容器中不存在 BeanName 為 messageSource 的 Bean 執行個體
// 手動建立一個 DelegatingMessageSource 執行個體, 用于接受 getMessage 方法調用。
DelegatingMessageSource dms = new DelegatingMessageSource();
// 添加父類 MessageSource
dms.setParentMessageSource(getInternalParentMessageSource());
// 将手動建立的 DelegatingMessageSource 指派給目前容器中的 messageSource
this.messageSource = dms;
// 以 messageSource 為 BeanNme 将 DelegatingMessageSource 類的執行個體注冊到一級緩存 singletonObjects 中
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
"': using default [" + this.messageSource + "]");
}
}
}
源碼很簡單,就是給 this.messageSource 屬性指派,但有一點我們要注意就是,手動注入 MessageSource 類型的 Bean 名稱必須是 “messageSource”。
三、refresh 方法之 initApplicationEventMulticaster
這部分和 Spring 的事件監聽機制有所關聯,那我們按照慣例先來了解了解 Spring 的事件監聽如何使用。
Spring 的事件監聽主要分三部分:
- 事件:ApplicationEvent,要自定義事件,則需要建立一個類繼承 ApplicationEvent。
- 事件釋出者:ApplicationEventPublisher 和 ApplicationEventMulticaster,因為 ApplicationContext 實作了 ApplicationEventPublisher,是以事件釋出可以直接使用 ApplicationContext。
- 事件監聽器:ApplicationListener,通過建立一個實作了 ApplicationListener 并注冊為 Spring bean 的類來接收消息。
既然如此,我們實作一個自己的監聽器就需要完成下面三件事情:
- 自定義一個事件
- 向 IOC 容器中注冊我們自己的監聽器
- 釋出事件
現在目标很明确了,那開始編寫案例:
1、自定義事件
public class MyEvent extends ApplicationEvent {
private String message;
public MyEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
}
2、寫一個自己的監聽器,監聽器的關注事件為 MyEvent
@Component
public class MyApplicationListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("MyApplicationListener 收到消息: " + event.getMessage());
}
}
3、編寫配置類
@Configuration
@ComponentScan(value = "cn.j3code.studyspring.listener")
public class MyListenerConfiguration {
}
4、測試
public class MyListenerMain {
public static void main(String[] args) {
// 讀取配置檔案啟動
AnnotationConfigApplicationContext annotationApplicationContext =
new AnnotationConfigApplicationContext(MyListenerConfiguration.class);
// 手動釋出事件
annotationApplicationContext.publishEvent(new MyEvent(annotationApplicationContext, "我釋出的一個消息,記得關注點贊"));
}
}
現在我們進入這個源碼,看看其實作原理。
入口
initApplicationEventMulticaster();
org.springframework.context.support.AbstractApplicationContext#initApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
// 擷取 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 判斷 beanFactory 中是否存在事件廣播中心bean執行個體
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
//存在時,beanFactory中的事件廣播中心bean執行個體指派給applicationEventMulticaster
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 不能存在,new 建立新的applicationEventMulticaster并指派給applicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
// 将建立的新事件廣播中心bean執行個體注冊到單例bean注冊中心
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
該方法和 initMessageSource 方法步驟非常相似,先判斷容器中是否存在對應的 Bean ,如果存在則不做處理,反之則向容器中添加相關 Bean。
當然 Spring 的事件監聽機制在這裡隻是一個開始,還需要結合 registerListeners 方法才能實作監聽功能,下節就來分析分析它。
四、refresh 方法之 onRefresh
空方法,需要子類實作
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
五、refresh 方法之 registerListeners
19 節中我們分析了多點傳播器的初始化,而這次要介紹的就是向多點傳播器中添加其它兩個中要的元件:
Listeners
、
Event
。
方法源碼
protected void registerListeners() {
// Register statically specified listeners first.
// 優先在事件多點傳播器中 注冊靜态指定的監聽器
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!
// 擷取實作ApplicationListener接口的監聽器
// 這個階段監聽器沒有初始化
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
// 擷取事件多點傳播器 ,并将實作ApplicationListener接口的Bean注冊到applicationListenerBeans中
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
// earlyApplicationEvents是早期的事件,在Spring IOC整個生命周期中,比多點傳播期的初始化要早出現
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
// 指派為null, help gc
this.earlyApplicationEvents = null;
// 存儲早期事件的集合被初始化
if (earlyEventsToProcess != null) {
// 周遊事件
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
// //添加到多點傳播器中
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}