Spring读源码系列08----容器扩展功能--下
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring读源码系列08----容器扩展功能--下相关的知识,希望对你有一定的参考价值。
Spring读源码系列08----容器扩展功能--下
- 注册BeanPostProcessor
- 初始化消息资源
- 初始化ApplicationEventMulticaster
- 空实现onRefresh
- 注册监听器
- 初始化非延迟加载单例
- finishRefresh
- 小结
注册BeanPostProcessor
前两篇文章已经讲述完了refresh方法中一部分的步骤,今天这篇文章就结束该方法的讲解,那么先从registerBeanPostProcessors方法讲起吧
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 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);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//这里是我们今天要分析的!!!
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
....
registerBeanPostProcessors
/**
实例化并注册所有 BeanPostProcessor bean,如果给定,则尊重显式顺序。
必须在应用程序 bean 的任何实例化之前调用。
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
可以看到具体执行过程是委托给了PostProcessorRegistrationDelegate完成的,这是一种很好的重构思想,大家可以学习一下,当然不是任何情况下都需要进行重构,而是考虑到代码量和当前代码与当前类的相关度情况下进行决策的
该代理类的registerBeanPostProcessors方法在上一篇文章中已经讲过了,下面我再贴出来一遍作为巩固:
PostProcessorRegistrationDelegate#registerBeanPostProcessors
//注册拦截 bean 创建的 bean 处理器。
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext)
//警告:虽然看起来可以轻松地重构此方法的主体以避免使用多个循环和多个列表,
//但使用多个列表和多次传递处理器名称是有意的。
//我们必须确保我们遵守 PriorityOrdered 和 Ordered 处理器的合同。
//具体来说,我们不能导致处理器被实例化(通过 getBean() 调用)或以错误的顺序在 ApplicationContext 中注册。
//拿到容器中所有实现了BeanPostProcessor接口的bean
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
//注册 BeanPostProcessorChecker,
//它会在 BeanPostProcessor 实例化期间创建 bean 时记录一条信息消息,
//即当 bean 不符合所有 BeanPostProcessor 处理的条件时。
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
//分别处理实现了priorityOrdered,ordered和啥都没有实现的以及内部使用的bean的后置处理器
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
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);
//MergedBeanDefinitionPostProcessor---合并bean的定义
//例如: AutowiredAnnotationBeanPostProcessor处理autowired注解
if (pp instanceof MergedBeanDefinitionPostProcessor)
internalPostProcessors.add(pp);
else if (beanFactory.isTypeMatch(ppName, Ordered.class))
orderedPostProcessorNames.add(ppName);
else
nonOrderedPostProcessorNames.add(ppName);
//先处理PriorityOrdered,然后注册
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
//再处理oreder接口
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames)
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
//判断是否是MergedBeanDefinitionPostProcessor
if (pp instanceof MergedBeanDefinitionPostProcessor)
internalPostProcessors.add(pp);
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
//处理没有实现任何优先级接口的bean
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.
//再处理internalPostProcessors即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).
//添加一个ApplicationListenerDetector后置处理器到处理器链尾部
//在refresh的prepareBeanFactory方法中已经添加过该后置处理器,这里是为了把他移动到处理器链尾部
//为啥要那么麻烦搞两次,这个应该有其自身原因
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors)
if (beanFactory instanceof AbstractBeanFactory)
// Bulk addition is more efficient against our CopyOnWriteArrayList there
((AbstractBeanFactory) beanFactory).addBeanPostProcessors(postProcessors);
else
for (BeanPostProcessor postProcessor : postProcessors)
beanFactory.addBeanPostProcessor(postProcessor);
可以看到prepareBeanFactory方法中就已经注册过了
初始化消息资源
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 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);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
//看这个地方
initMessageSource();
...
initMessageSource
这里关于消息国际化部分,不是本文重点,但是又不想直接跳过,因此我就直接把书上对应部分内容拿了过来
/**
* Initialize the MessageSource.
* Use parent's if none defined in this context.
*/
protected void initMessageSource()
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//MESSAGE_SOURCE_BEAN_NAME--->messageSource
//说明消息数据源的beanName必须是messageSource
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME))
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent 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
//容器中不存在messageSource的bean,那么创建一个默认的DelegatingMessageSource
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
//注册这个默认创建的DelegatingMessageSource
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled())
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
MessageSource在哪里被使用呢?
@Override
public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale)
return getMessageSource().getMessage(code, args, defaultMessage, locale);
具体使用就如下了:
这里国际化就到此结束了,因为国际化目前使用较少,因此这里就小篇幅就讲解了,我们把重心放在更加重要的组件上面
初始化ApplicationEventMulticaster
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 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);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
...
使用场景演示
在正式讲解spring的事件派发器前,还是先来复习一下spring的事件监听器的使用
- 定义监听事件
public class TestEvent extends ApplicationEvent
private Object source;
public TestEvent(Object source)
super(source);
this.source=source;
public void processObj()
System.out.println("TestEvent当前正在处理的事件为: "+source);
- 定义监听器
public class TestListener implements ApplicationListener
@Override
public void onApplicationEvent(ApplicationEvent event)
if(event instanceof TestEvent)
TestEvent testEvent = (TestEvent) event;
testEvent.processObj();
- 监听器注入容器—后置处理器自动识别(ApplicationListenerDetector)
<bean class="org.test.TestListener"/>
- 测试
public class MainTest
public static void main(String[] args)
ClassPathXmlApplicationContext xmlApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
xmlApplicationContext.publishEvent(new TestEvent("我是消息"));
initApplicationEventMulticaster
protected void initApplicationEventMulticaster()
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//APPLICATION_EVENT_MULTICASTER_BEAN_NAME-->applicationEventMulticaster
//和messagesource一样,bean的名字是固定不变的
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME))
//如果容器中存在用户自定义的applicationEventMulticaster,那么就使用用户注入的
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() + "]");
SimpleApplicationEventMulticaster内部如何派发事件的
废话不多说,咱们上源码:
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster
@Nullable
private Executor taskExecutor;
@Nullable
private ErrorHandler errorHandler;
@Nullable
private volatile Log lazyLogger;
public SimpleApplicationEventMulticaster()
public SimpleApplicationEventMulticaster(BeanFactory beanFactory)
setBeanFactory(beanFactory);
以上是关于Spring读源码系列08----容器扩展功能--下的主要内容,如果未能解决你的问题,请参考以下文章
Spring读源码系列01---Spring核心类及关联性介绍
Spring读源码系列番外篇08---BeanWrapper没有那么简单--上