本文接着上一篇 《Spring容器的基本实现之源码分析-上篇》 接着来继续分析 Spring容器启动流程。
本篇将会讨论 Spring 启动流程中剩下的几个核心方法, 包括 BeanFactory 后处理、初始化非延迟加载单例、finishRefresh这几个方法的具体流程。
下篇目录:
下篇目录.png
BeanFactory 的后处理
BeanFactory 作为 Spring 中容器功能的基础,用于存放所有已加载的 bean ,为了保证程序的高度可扩展, Spring 针对 BeanFactory 做了大量的扩展,比如我们熟知的 PostProcessor 等都是在这里实现的。
激活注册的BeanFactoryPostProcessor
首先我们先了解下BeanFactoryPostProcessor的用法。简单来说 BeanFactoryPostProcessor 和前面说的BeanPostProcessor类似,可以对bean的定义(配置元数据) 进行处理。那么它们之前的区别是什么呢?
简单来说,SpringIOC 允许BeanFactoryPostProcessor 在容器实际实例化任何其他的bean之前读取配置的元数据,它的作用于是容器级的,如果是想改变实际的bean实例,那么最好还是使用 BeanPostProcessor 。在 Spring中存在对于 BeanFactoryPostProcessor 的典型应用,比如 PropertyPlaceholderConfigurer。
-
BeanFactoryPostProcessor 的典型应用: PropertyPlaceholderConfigurer
我们在配置Spring的Bean描述文件时,经常会使用属性变量引用:
<bean id="helloMessage" class="com.ccgogoing.domain.HelloMessage"> <property name="meg" value="${bean.message}"/> </bean>
这种使用变量的方式,就是Spring的分散配置,可以在另外的配置文件中为
bean.message
指定值。如在bean.properties
文件中指定:bean.message=Hello World!
当访问bean时,其属性就会被置为配置的字符串,但问题是Spring怎样知道存在这样的配置文件呢? 这就要靠
PropertyPlaceholderConfigurer
这个类的bean:<bean id="msgHandler" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>config/bean.properties</value> </list> </property> </bean>
在这个bean中指定了配置文件为 config/bean.properties ,这里我们似乎明白了,但仔细想一下,这个"msgHandler" 只是配置为Spring管理的一个 Bean,并没有被别的bean或者对象引用,Spring 的 BeanFactory 怎样知道要从这个 bean中获取配置信息呢?
查看 PropertyPlaceholderConfigurer 的层次结构,可以看到这个类间接继承了 BeanFactoryPostProcessor 接口。这是一个很特别的接口,当Spring加载任何实现了这个接口的bean的配置时,都会在 bean 工厂载入所有bean 的配置之后执行 postProcessorBeanFactory 方法。在 PropertyResourceConfigurer 类中实现了postProcessorBeanFactory 方法,在方法中先后调用了 mergeProperties、 convertProperties、 processProperties这三个方法,分别得到配置,将得到的配置转换为合适的类型,最后将配置的内容告知BeanFactory。
PlaceholderConfigurerSupport层级.jpg@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
try {
Properties mergedProps = mergeProperties();
// Convert the merged properties, if necessary.
convertProperties(mergedProps);
// Let the subclass process the properties.
processProperties(beanFactory, mergedProps);
}
catch (IOException ex) {
throw new BeanInitializationException("Could not load properties", ex);
}
}
正是通过实现 BeanFactoryPostProcessor 接口, BeanFactory 会在实例化任何 bean 之前获得配置信息,从而能够正确解析 bean 描述文件中的变量引用。
-
使用自定义的 BeanFactoryPostProcessor
我们实现一个
BeanFactoryPostProcessor
,去除潜在的‘流氓’属性值来展示自定义 BeanFactoryPostProcessor 的创建和使用,例如在 bean 定义中留下 bollocks 这样的字眼。配置文件 beans.xml
<bean id="bfpp" class="com.ccgogoing.domain.ObScenityRemovingBeanFactoryPostProcessor">
<property name="obscenties">
<set>
<value>bollocks</value>
<value>winky</value>
<value>bum</value>
<value>MicroSoft</value>
</set>
</property>
</bean>
<bean id="simple" class="com.ccgogoing.domain.SimplePostProcessor">
<property name="password" value="bollocks"/>
<property name="username" value="imaginecup"/>
<property name="connectString" value="MicroSoft"/>
</bean>
ObScenityRemovingBeanFactoryPostProcessor.java
public class ObScenityRemovingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private Set<String> obscenties;
public ObScenityRemovingBeanFactoryPostProcessor() {
this.obscenties = new HashSet<>();
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String [] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
StringValueResolver stringValueResolver = strVal -> {
if (isObscene(strVal)) {
return "*****";
}
return strVal;
};
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(stringValueResolver);
visitor.visitBeanDefinition(beanDefinition);
}
}
public boolean isObscene (Object val) {
String potentialObscenity = val.toString().toUpperCase();
return this.obscenties.contains(potentialObscenity);
}
public void setObscenties(Set<String> obscenties) {
this.obscenties.clear();
for (String obscenity : obscenties) {
this.obscenties.add(obscenity.toUpperCase());
}
}
}
测试类
@Test
public void testObscenityPostProcessor() {
ConfigurableListableBeanFactory bf = new XmlBeanFactory(new ClassPathResource("beans.xml"));
BeanFactoryPostProcessor beanFactoryPostProcessor = (BeanFactoryPostProcessor) bf.getBean("bfpp");
beanFactoryPostProcessor.postProcessBeanFactory(bf);
System.out.println(bf.getBean("simple"));
}
输出结果
SimplePostProcessor{connectString='*****', password='*****', username='imaginecup'}
通过自定义的 BeanFactoryPostProcessor Spring 很好的实现了屏蔽掉 obscenties 定义的不应该展示的属性。
-
激活
BeanFactoryPostProcessor
上面了解了 BeanFactoryPostProcessor 的用法之后我们在深入研究其调用过程。
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<String>();
// 对 BeanDefinitionRegistry 类型的处理
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
// 硬编码注册的后处理器
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 对于BeanDefinitionRegistryPostProcessor类型的,在BeanFactoryPostProcessor的基础上还有自己定义的方法,需要先调用
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
// 记录常规的BeanFactoryPostProcessor
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 配置注册的后置处理器
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 先调用实现了PriorityOrdered 接口的
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// BeanDefinitionRegistryPostProcessor的特殊处理
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 接下来调用 实现了Ordered 接口的
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 处理剩余的BeanDefinitionRegistryPostProcessors,直到没有
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 激活BeanDefinitionRegistryPostProcessor的postProcessBeanFactory,之前激活的是postProcessBeanDefinitionRegistry
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 激活硬编码注册的常规postProcessors
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
// bean工厂非BeanDefinitionRegistry,激活硬编码的beanFactoryPostProcessors
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 对于配置中读取的BeanFactoryPostProcessor的处理
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
// 对后置处理器进行分类
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above 上面第一步已经处理
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// 对于实现PriorityOrdered接口的 按照优先级进行排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 按照order进行排序
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 无序,直接调用
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
从上面的方法中我们发现,对于 BeanFactoryPostProcessor 的处理分为两种情况进行:
一种是 ConfigurableListableBeanFactory 属于 BeanDefinitionRegistry ,则需要处理 BeanDefinitionRegistryPostProcessor,另外一种是 beanFactory 不属于 BeanDefinitionRegistry 则只需要处理 BeanFactoryPostProcessor。而对于这两种情况 则都需要考虑硬编码注册的后置处理器以及通过配置注册的后置处理器。
这里我们一起看下 BeanDefinitionRegistry 类型的处理过程,因为非BeanDefinitionRegistry 类型的只需要进行普通BeanFactoryPostProcessor 的处理。
(1)对于硬编码注册的后置处理器,主要是通过 AbstractApplicationContext 中添加后置处理器的方法 addBeanFactoryPostProcessor 进行添加:
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
}
添加的后处理器被放在beanFactoryPostProcessors 中,而在调用处理 BeanFactoryPostProcessor 时会判断beanFactoryPostProcessors 是否有数据。由于 BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor ,因此它不但有 BeanFactoryPostProcessor 的特性同时还有自定义的个性化方法,所以这里需要从beanFactoryPostProcessors 中过滤出BeanDefinitionRegistryPostProcessor 类型的后处理器,进行其个性化方法 postProcessBeanDefinitionRegistry 的调用。
(2)记录后处理器使用了两个List。 registryProcessors 记录 BeanDefinitionRegistryPostProcessor 这种特殊的后处理器,regularPostProcessors 记录通过硬编码注册的BeanFactoryPostProcessor 类型的处理器。
(3) 将通过配置注册的 BeanDefinitionRegistryPostProcessor 按照优先级排序并调用postProcessBeanDefinitionRegistry 然后加入到registryProcessors 这个List中。对于这两个List进行统一的调用 BeanFactoryPostProcessor 类的 postProcessBeanFactory方法。
(4) 通过配置注册的普通BeanFactoryPostProcessor 处理。和BeanDefinitionRegistryPostProcessor 处理流程类似。
BeanDefinitionRegistryPostProcessor 只对 BeanDefinitionRegistry 类型的beanFactory有效,所以如果 beanFactory 并不是 BeanDefinitionRegistry 类型,则只需要处理 BeanFactoryPostProcessor ,包括硬编码注册和配置注册的后处理器。
认真看的同学会发现,对于硬编码方法注册的 BeanFactoryPostProcessor 不需要作任何排序,但是在配置文件中读取的处理器,Spring并不会保证读取的顺序。所以为了保证用户的调用顺序的要求,Spring对于后处理器的调用支持按照PriorityOrdered 或者Ordered的调用顺序。
注册BeanPostProcessor
上面我们提到了 BeanFactoryPostProcessor 的调用,这一节我们学习 BeanPostProcessor ,但是这里并不是调用而是注册。真正的调用其实是在 bean 的实例化阶段。这是一个很重要的步骤,由于不调用后处理器导致很多功能 BeanFactory 不支持。
下面我们继续探讨 registerBeanPostProcessors 的方法实现。
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
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;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
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.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
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.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
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.
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).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
BeanFactoryPostProcessor 和 BeanPostProcessor 两者之间区别不大,感兴趣的可以再看下上面代码,相信不难看懂。
初始化消息资源
这里主要进行国际化处理,即常见的多语言app,需要按照客户端的语言返回不同的页面 。 Spring 定义了访问国际化信息的 MessageSource 接口,并提供了几个易用的实现类。 Message 接口分别被 HierarchicalMessageSource 和ApplicationContext 接口扩展。
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
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.isDebugEnabled()) {
logger.debug("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
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 + "]");
}
}
}
初始化ApplicationEventMulticaster
在开始研究 Spring 的时间传播器之前,我们先来看一个 Spring 的事件监听的简单用法。
-
定义监听事件。
public class TestEvent extends ApplicationEvent{ public String msg; /** * Create a new ApplicationEvent. * * @param source the object on which the event initially occurred (never {@code null}) */ public TestEvent(Object source) { super(source); } public TestEvent(Object source,String msg) { super(source); this.msg = msg; } public void print() { System.out.println(msg); } }
-
定义监听器
public class TestListener implements ApplicationListener{ @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof TestEvent) { TestEvent testEvent = (TestEvent) event; testEvent.print(); } } }
-
添加配置文件
<bean id="testListener" class="com.ccgogoing.listener.TestListener"/>
-
测试
@Test public void testEvent() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); TestEvent testEvent = new TestEvent("hello","msg"); applicationContext.publishEvent(testEvent); }
当程序运行时,Spring 会将发出的 TestEvent 事件转给我自定义的 TestLinstener 进行进一步处理。
相信很多人看到这里,一下子会想到了观察者模式,这确实是个典型的应用,可以在比较关心的事件结束后及时进行处理。那么我们接下来一起看看 ApplicationEventMulticaster 是如何被初始化的,以确保功能的正确运行。
initApplicationEventMulticaster 的方式比较简单,无非考虑两种情况。
- 如果用户自定义了事件广播器则使用自定义的广播器。
- 如果用户没有自定义的事件广播器,则使用默认的 ApplicationEventMulticaster。
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
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 + "]");
}
}
}
按照之前我们了解的事件监听的顺序和逻辑,我们推断,作为广播器,一定是用于存放监听器并在合适的时候调用监听器,那么我们不妨进入默认的广播器实现 SimpleApplicationEventMulticaster 来一探究竟。
下面这段代码是关键所在:
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@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);
}
}
}
可以看到,当产生Spring 事件的时候会默认使用 SimpleApplicationEventMulticaster 的 multicastEvent 方法来广播事件,遍历所有监听器,并使用监听器中的 onApplicationEvent 方法来进行监听器处理。
注册监听器
上面在学习 Spring 广播器的时候反复提到了事件监听器,那么在 Spring注册监听器的时候又做了哪些逻辑操作呢?
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!
// 配置文件注册的监听器处理
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
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);
}
}
}
初始化非延迟加载单例
完成 BeanFactory 的初始化工作,其中包括 ConversionService 的设置、配置冻结 以及 非延迟加载的 bean 的初始化工作。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
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.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 冻结所有 bean 定义,说明注册的bean定义将不被修改或任何进一步的处理
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化剩下的所有非延迟加载的单实例bean
beanFactory.preInstantiateSingletons();
}
-
ConversionService 的设置
Spring提供了一种类型转换方式:使用converter,比如将String 转换为 Date。下面我们使用一个简单的示例来了解下 Converter 的使用方式。
(1) 定义转换器
public class String2DateConverter implements Converter<String,Date> { @Override public Date convert(String source) { try { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = sdf.parse(source); return date; } catch (Exception e) { return null; } } }
(2) 注册
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="com.ccgogoing.domain.String2DateConverter"/> </list> </property> </bean>
(3) 测试
@Test public void testString2DateConvert() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); DefaultConversionService conversionService = (DefaultConversionService) applicationContext.getBean("conversionService"); conversionService.addConverter(new String2DateConverter()); String dateStr = "2019-02-21"; Date date = conversionService.convert(dateStr,Date.class); System.out.println(date); }
通过以上功能我们看到了 Converter 和 ConversionService 提供的便利功能,其中的配置就是在当前函数中初始化的。
-
冻结配置
冻结所有bean的定义,说明注册的bean定义将不再做任何修改或进行任何一进步的处理。
@Override public void freezeConfiguration() { this.configurationFrozen = true; this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames); }
-
初始化非延迟加载
ApplicationContext 实现的默认行为就是在启动时将所有的单例 bean 提前实例化。 提前实例化意味着作为初始化过程的一部分, ApplicationContext 实例会创建并配置所有的单例 bean。通常情况下这是一件好事,因为这样在配置中的任何错误就会被即刻发现(否则可能要花几个小时甚至几天)。 而这个实例化的过程就是在 preInstantiateSingletons 中完成的。
@Override public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Boolean run() { return ((SmartFactoryBean<?>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { smartSingleton.afterSingletonsInstantiated(); return null; } }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
finishRefresh
在 Spring 中提供了 LifeCycle 接口, LifeCycle 中包含start/stop 方法,实现此接口后Spring 会保证在启动的时候调用 start 方法开始生命周期,并在 Spring 关闭的时候调用 stop 方法来结束生命周期,通常用来配置后台程序,再启动后一直运行(如对MQ进行轮询等)。而 ApplicationContext 的初始化最后正是保证了这一功能的实现。
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
-
initLifecycleProcessor
当ApplicationContext 启动或停止时,它会通过LifeCycleProcessor来与所有生命的 bean 的周期做状态更新,而在LifeCycleProcessor 的使用前首先需要进行初始化。
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isDebugEnabled()) {
logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate LifecycleProcessor with name '" +
LIFECYCLE_PROCESSOR_BEAN_NAME +
"': using default [" + this.lifecycleProcessor + "]");
}
}
}
-
OnRefresh
启动所有实现了 LifeCycle 接口的 bean。
@Override
public void onRefresh() {
startBeans(true);
this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) {
Lifecycle bean = entry.getValue();
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(entry.getKey(), bean);
}
}
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<Integer>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
-
publishEvent
当完成ApplicationContext初始化的时候,要通过 Spring 中的事件发布机制来发布 ContextRefreshedEvent 事件,以保证对应的监听器可以做进一步的逻辑处理。
protected void publishEvent(Object event, ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<Object>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
至此,Spring 容器就启动完毕了,相信大家仔细看完这两篇文章一定会对 Spring 的原理有更进一步的了解。
传送门:
网友评论