深资架构师经验分享,Spring源码解析:高级容器的扩展内幕
liebian365 2024-11-09 13:48 26 浏览 0 评论
本篇我们一起来详细探究一下基于 ApplicationContext 的容器初始化和注入过程,至于 ApplicationContext 的使用方式,广大开发者应该是信手拈来,这里还是简单的举例一下:
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-core.xml");
MyBean myBean = (MyBean) context.getBean("my-bean");
myBean.sayHello();
相对于 BeanFactory 来说,使用方式上没有太大的区别,也是分成两步走,第一步加载配置,第二步执行 bean 实例的创建和初始化过程。其中第二步与之前我们探究 BeanFactory 时的 getBean 方法复用的是一套逻辑,因为由前面文章的继承关系我们已经知道 ApplicationContext 不是一个新的策略实现类,而是从 BeanFactory 扩展而来,并且将主要的精力都放在了对于配置文件加载的扩展上,这样的实现也是很容易理解的,毕竟第一步是和开发者息息相关的,是开发者能够直观配置的东西,这一块的优化能够直观反映在框架的使用上,而第二步主要是框架内部的事情,所以接下来我们主要探究第一步的实现过程,而第二步则可以参考前面专门讲解 Bean 实例创建与初始化过程的文章。
第一步的逻辑暴露给开发者的接口位于 ClassPathXmlApplicationContext 的构造方法中,我们通过 new ClassPathXmlApplicationContext("classpath:spring-core.xml") 来触发容器执行配置加载的逻辑:
public ClassPathXmlApplicationContext(String configLocation)throwsBeansException{
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations,booleanrefresh, ApplicationContext parent)throwsBeansException{
super(parent);
// 支持多个配置文件以数组形式传入
this.setConfigLocations(configLocations);
if (refresh) {
// refresh方法几乎包含了ApplicationContext的全部功能
this.refresh();
}
}
方法第一步需要记录传递的配置文件路径,因为可以同时传递多个配置文件,并且配置文件的组织形式不一定是容器能够理解的方式,所以还需要执行一些解析的工作:
public void setConfigLocations(String... locations){
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
// 解析给定的路径,将占位符替换成具体的值
this.configLocations[i] = this.resolvePath(locations[i]).trim();
}
} else {
this.configLocations = null;
}
}
我们传递的配置文件可能存在一些占位符来代替一些变量,所以在上述方法中容器需要对这些变量进行解析,并用真实指代的值进行替换,最终将路径记录到实例字符串数组变量 configLocations 中。
接下来需要调用 refresh 方法,该方法是 ApplicationContext 的核心,可以看做是对 ApplicationContext 功能的一个总调度器:
public void refresh()throwsBeansException, IllegalStateException{
synchronized (this.startupShutdownMonitor) {
// 1. 初始化 refresh 的上下文环境
this.prepareRefresh();
// 2. 初始化 BeanFactory,加载并解析配置
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
/* ---至此,完成了简单容器的所有功能,下面开始对简单容器进行增强--- */
// 3. 对 BeanFactory 进行功能增强
this.prepareBeanFactory(beanFactory);
try {
// 4. 后置处理 beanFactory,交由子类实现
this.postProcessBeanFactory(beanFactory);
// 5. 调用已注册的 BeanFactoryPostProcessor
this.invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessor,仅仅是注册,调用在getBean的时候
this.registerBeanPostProcessors(beanFactory);
// 7. 初始化国际化资源
this.initMessageSource();
// 8. 初始化事件广播器
this.initApplicationEventMulticaster();
// 9. 留给子类实现的模板方法
this.onRefresh();
// 10. 注册事件监听器
this.registerListeners();
// 11. 实例化所有非延迟加载的单例
this.finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新过程,发布应用事件
this.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.
this.destroyBeans();
// Reset 'active' flag.
this.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...
this.resetCommonCaches();
}
}
}
我们先来概括一下整个方法的执行过程,然后再来逐个过程展开细说:
- 初始化 refresh 的上下文环境
- 初始化 BeanFactory,加载并解析配置
- 对 BeanFactory 进行功能增强
- 后置处理器 BeanFactory
- 调用已注册的 BeanFactoryPostProcessor
- 注册各个 BeanPostProcessor
- 初始化的国际化资源
- 初始化事件广播器
- 注册事件监听器
- 实例化所有非延迟加载的单例
- 完成刷新过程,发布应用事件
上述过程中到第 2 步为止已经完成了简单容器中解析配置文件,以 BeanDefinition 进行容器内表示的全部过程,从第 3 步开始均是属于高级容器的扩展实现。
1. 初始化 refresh 的上下文环境
方法的第一步就是对刷新需要的上下文环境执行一个初始化操作,这其中包含一些标记变量的赋值和一些属性值的处理工作:
protected void prepareRefresh(){
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 初始化属性,留给子类覆盖实现
this.initPropertySources();
// 验证必要属性是否都已经被解析
// see ConfigurablePropertyResolver#setRequiredProperties
this.getEnvironment().validateRequiredProperties();
// 存放需要提前感知的应用事件
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
Spring 在这里提供了供子类覆盖实现的模板方法 initPropertySources,从而可以让子类拥有修改属性的机会。一些属性对于系统来说是必要的,缺失则会影响系统的正常逻辑,对于这类属性我们可以调用 setRequiredProperties 方法将其设置为 “required”,这样在本方法中就会验证其是否存在,如果不存在则会提前抛出异常。
2. 初始化 BeanFactory,加载并解析配置
本步骤中包含了加载和解析配置文件的复杂逻辑,并返回创建的 ConfigurableListableBeanFactory 对象,前面我们曾强调过 ConfigurableListableBeanFactory 在 BeanFactory 的继承体系中占有着相当重要的地位,它是包含容器完整功能的一个基本实现。
protectedConfigurableListableBeanFactoryobtainFreshBeanFactory(){
// 1. 初始化BeanFactory,并执行加载和解析配置操作,在这一步已经得到了beanDefinition实例
this.refreshBeanFactory();
// 2. 返回beanFactory实例
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
上述方法的逻辑就是创建 beanFactory 对象并返回,refreshBeanFactory 是整个方法的核心:
protected final void refreshBeanFactory()throwsBeansException{
// 存在beanFactory
if (this.hasBeanFactory()) {
// 注销所有的单例
this.destroyBeans();
// 重置beanFactory
this.closeBeanFactory();
}
try {
// 创建DefaultListableBeanFactory对象,DefaultListableBeanFactory是容器的基本实现
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
// 指定序列化id,必要的话可以反序列化得到beanFactory对象
beanFactory.setSerializationId(this.getId());
/*
* 1. 是否允许配置同名称的bean(后面的配置会覆盖前面的配置)
* 2. 是否允许循环依赖
*/
this.customizeBeanFactory(beanFactory);
// 加载并解析xml配置,由静态配置转为beanDefinition
this.loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
方法中首先会判断是否已经有创建的 beanFactory 实例存在,有的话则重置,然后重新创建 beanFactory 对象,创建的过程中会执行 loadBeanDefinitions 逻辑,如果看过本系列之前的文章,一定会理解本方法的作用并且体会到其过程的复杂程度,该方法包含了获取配置文件 Document 对象,并执行默认标签和自定义标签的解析,将配置封装到 beanDefinition 对象中返回的逻辑,经过这一步骤,xml 中静态的配置文件就会转变成内存中的数据结构存放于容器中。
3. 对 BeanFactory 进行功能增强
前面两个步骤已经完成了简单容器的全部功能,从这里开始对简单容器进行扩展增强处理。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory){
// 设置使用上下文的类加载器
beanFactory.setBeanClassLoader(this.getClassLoader());
// 设置表达式解析器以提供EL表达式风格的属性调用(3.0版本引入)
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 增加默认属性编辑器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
/*
* 添加后置处理器ApplicationContextAwareProcessor, 如果实现了相应的 Aware 接口,则注入对应的资源
* 1. EnvironmentAware
* 2. EmbeddedValueResolverAware
* 3. ResourceLoaderAware
* 4. ApplicationEventPublisherAware
* 5. MessageSourceAware
* 6. ApplicationContextAware
*/
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 忽略以下接口的自动装配,对应上一行代码中处理的接口
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// 注册几个自动装配的规则
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 注册后置处理器 ApplicationListenerDetector,用于探测 ApplicationListener 类型接口
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 增加对 AspectJ 的支持
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册默认系统环境相关的bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
// Environment
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
// System Properties
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
// System Environment
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
prepareBeanFactory 方法对 BeanFactory 的功能增强主要包括:
- 增加了对 Spring 表达式(SpEL)的支持。
- 增加了对属性编辑器的支持。
- 增加了对一些 Aware 类的自动装配支持。
- 增加了对 ApplicationListener 类型 bean 的发现支持。
- 增加了对 AspectJ 的支持。
- 注册了几个系统环境变量相关的 bean。
Spring Expression Language(SpEL)是在 3.0 版本引入的新特性,允许我们在配置时候以类似 EL 表达式的方式去引用上下文中的变量,未接触过的同学可以自己去体验一下,笔者用的也不是很多。
在配置 bean 的时候,如果我们希望对某一类型的属性执行一些处理,可以通过自定义属性编辑器来实现,典型的应用场景就是对时间类型属性的转换,假设我们的 bean 存在 LocalDate 类型的属性,这个时候我们直接以字符串配置进行注入是会出现异常的,这个时候我们可以自定义属性编辑器来实现类型的转换:
public class MyDatePropertyEditorextends PropertyEditorSupportimplements InitializingBean{
private String format = "yyyy-MM-dd";
private DateTimeFormatter dtf;
@Override
public void afterPropertiesSet()throwsException{
dtf = DateTimeFormatter.ofPattern(format);
}
@Override
public void setAsText(String text)throwsIllegalArgumentException{
if (!StringUtils.hasText(text)) {
this.setValue(null);
return;
}
this.setValue(LocalDate.parse(text));
}
publicMyDatePropertyEditorsetFormat(String format){
this.format = format;
return this;
}
}
<!--注册自定义属性解析器-->
<beanclass="org.springframework.beans.factory.config.CustomEditorConfigurer">
<propertyname="customEditors">
<map>
<entrykey="java.time.LocalDate">
<beanclass="org.zhenchao.editor.MyDatePropertyEditor">
<propertyname="format"value="yyyy-MM-dd"/>
</bean>
</entry>
</map>
</property>
</bean>
我们自定义的属性编辑器 MyDatePropertyEditor 通过时间格式化工具对指定模式的字符串格式日期执行转换和注入,而上述转换只能在我们以 ApplicationContext 的方式加载 bean 的前提下才生效,如果我们以 BeanFactory 的方式加载 bean,还是会抛出异常,毕竟这属于高级容器中增强的功能。
当我们定义的 bean 实现了 Aware 接口的时候,我们总能比一般的 bean 多拿到一些资源,而此处对于 beanFactory 的扩展也增加了对一些 Aware 类自动装配的支持。ApplicationContextAwareProcessor 实现了 BeanPostProcessor 接口,并主要实现了 postProcessBeforeInitialization 逻辑:
publicObjectpostProcessBeforeInitialization(finalObject bean, String beanName)throwsBeansException{
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
publicObjectrun(){
invokeAwareInterfaces(bean);
return null;
}
}, acc);
} else {
// 核心在于激活 Aware
this.invokeAwareInterfaces(bean);
}
return bean;
}
上述方法的核心在于 invokeAwareInterfaces 方法:
private void invokeAwareInterfaces(Object bean){
if (bean instanceof Aware) {
// EnvironmentAware
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
// EmbeddedValueResolverAware
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
// ResourceLoaderAware
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
// ApplicationEventPublisherAware
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
// MessageSourceAware
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
// ApplicationContextAware
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
整个方法的逻辑很直观,判断当前类所实现的 Aware 接口,然后将相应的资源给到该 bean,以 ApplicationContextAware 举例来说,实现了该接口的 bean 都持有 ApplicationContext 的实例,而上述方法也正是调用了相应的 setter 将 ApplicationContext 实例注入到 bean 实例中。
在 4.3.x 版本中增加了对实现了 ApplicationListener 接口的探测,ApplicationListenerDetector 实现了 MergedBeanDefinitionPostProcessor 和 DestructionAwareBeanPostProcessor 后置处理接口,并相应实现了这些后置处理器定义的模板方法,其中核心的方法 postProcessAfterInitialization 逻辑如下:
publicObjectpostProcessAfterInitialization(Object bean, String beanName){
if (this.applicationContext != null && bean instanceof ApplicationListener) {
// 实现了 ApplicationListener 接口
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) { // 单例
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
} else if (Boolean.FALSE.equals(flag)) { // 非单例
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
// inner bean with other scope - can't reliably process events
logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface but is not reachable for event multicasting by its containing ApplicationContext " +
"because it does not have singleton scope. Only top-level listener beans are allowed to be of non-singleton scope.");
}
this.singletonNames.remove(beanName);
}
}
return bean;
}
该方法针对实现了 ApplicationListener 接口的单例,统一注册到监听器集合中监听事件,而方法中的 singletonNames 变量则是在 postProcessMergedBeanDefinition 方法中进行构建:
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName){
if (this.applicationContext != null) {
this.singletonNames.put(beanName, beanDefinition.isSingleton());
}
}
由此我们可以知道 singletonNames 中存放了 beanName,以及对应的 bean 是否是单例的关联关系。
4. 后置处理器 BeanFactory
refresh 中设置一个用于处理 BeanFactory 的模板方法:postProcessBeanFactory(beanFactory)。该方法的实现逻辑交由子类,用于增强 Spring 框架的可扩展性。
5. 调用已注册的 BeanFactoryPostProcessor 后置处理器
BeanFactoryPostProcessor 用于对 BeanFactory 实例进行后置处理,这和 BeanPostProcessor 以 bean 实例作为处理对象有着本质的区别,所以说代码执行到这里就已经开始激活这些已经注册的 BeanFactoryPostProcessor 后置处理器处理前面已经准备好的 BeanFactory 对象,但是需要清楚的是这个时候还没有开始创建 bean 实例。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory){
// 激活 BeanFactoryPostProcessor 后置处理器
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
// AOP支持:LoadTimeWeaver
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
注意这里传入的 this.getBeanFactoryPostProcessors() 参数全部是编码注册的 BeanFactoryPostProcessor 通过调用如下方法进行添加:
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor){
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
}
笔者最开始看这段代码的时候,潜意识认为所有的 BeanFactoryPostProcessor 都是记录在 beanFactoryPostProcessors 代码段中的,如果以配置的方式使用过 BeanFactoryPostProcessor 的同学都知道,BeanFactoryPostProcessor 的配置仅仅需要在配置文件中配置一个 bean,比如:
<beanid="myBeanFactoryPostProcessor"class="org.zhenchao.processor.MyBeanFactoryPostProcessor"/>
我们不需要在其它任何地方去注册或引用 myBeanFactoryPostProcessor,所以我就去代码中探究 Spring 是如何把上述配置给添加到 beanFactoryPostProcessors 中的,即在哪里调用了 addBeanFactoryPostProcessor 方法,结果一无所获,因为出发点就是错误的,下面的源码中你将看到这里传递的仅仅是编码注册的 BeanFactoryPostProcessor,而配置的方式通过其他的方式获取到的:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
/*beanFactoryPostProcessors 保存了所有通过编码注册的 BeanFactoryPostProcessor*/
Set<String> processedBeans = new HashSet<String>();
// 如果是 BeanDefinitionRegistry 类型
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); // 记录注册的 BeanFactoryPostProcessor 类型处理器
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); // 记录注册的 BeanDefinitionRegistryPostProcessor 类型处理器
// 一. 遍历处理编码注册的 BeanFactoryPostProcessor
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
/*
* 如果是 BeanDefinitionRegistryPostProcessor (继承自 BeanFactoryPostProcessor)
* 1. 执行 BeanDefinitionRegistryPostProcessor 中扩展的方法 postProcessBeanDefinitionRegistry
* 2. 记录到 registryPostProcessors 集合中,用于后面处理继承自 BeanFactoryPostProcessor 的方法
*/
BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
registryPostProcessors.add(registryPostProcessor);
} else {
// 否则就是 BeanFactoryPostProcessor
regularPostProcessors.add(postProcessor);
}
}
// 二. 获取配置的 BeanDefinitionRegistryPostProcessor 类型后置处理器
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
/* 1.激活所有实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor */
List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 对处理器进行排序
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registryPostProcessors.addAll(priorityOrderedPostProcessors);
// 执行 BeanDefinitionRegistryPostProcessor 中扩展的方法
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
/* 2.激活所有实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessor */
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 对处理器进行排序
sortPostProcessors(beanFactory, orderedPostProcessors);
registryPostProcessors.addAll(orderedPostProcessors);
// 执行 BeanDefinitionRegistryPostProcessor 中扩展的方法
invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
/* 3.激活剩余的 BeanDefinitionRegistryPostProcessor */
boolean reiterate = true; // 反复的
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) { // 没有处理过的
BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
registryPostProcessors.add(pp);
processedBeans.add(ppName);
// 执行 BeanDefinitionRegistryPostProcessor 中扩展的方法
pp.postProcessBeanDefinitionRegistry(registry);
reiterate = true;
}
}
}
// 激活所有 BeanDefinitionRegistryPostProcessor 后置处理器中的 postProcessBeanFactory 方法
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
// 激活所有 BeanFactoryPostProcessor 后置处理器中的 postProcessBeanFactory 方法
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
} else {
// 如果不是 BeanDefinitionRegistry 类型,直接激活所有编码注册的 BeanFactoryPostProcessor 后置处理器
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 获取配置的 BeanFactoryPostProcessor 类型后置处理器
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
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)) {
// 跳过已经处理过的 bean
} else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 实现了 PriorityOrdered 接口
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 实现了 Ordered 接口
orderedPostProcessorNames.add(ppName);
} else {
// 其它
nonOrderedPostProcessorNames.add(ppName);
}
}
/* 1.激活所有实现了 PriorityOrdered 接口的 BeanFactoryPostProcessor */
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
/* 2.激活所有实现了 Ordered 接口的 BeanFactoryPostProcessor */
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(beanFactory, orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
/* 3.激活剩余的 BeanFactoryPostProcessor */
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 清理工作
beanFactory.clearMetadataCache();
}
我们可以看到针对编码注册和以配置方式注册的 BeanFactoryPostProcessor,Spring 的获取方式是不一样的,前者都是注册到前面所说的 beanFactoryPostProcessors 集合中,而后者都是通过 BeanFactory 的 getBeanNamesForType 方法获取到的。
上述方法先判断 BeanFactory 是不是 BeanDefinitionRegistry 类型,如果是的话则专门处理,这样设计是因为继承自 BeanFactoryPostProcessor 的 BeanDefinitionRegistryPostProcessor 需要专门处理这种类型:
public interface BeanDefinitionRegistryPostProcessorextends BeanFactoryPostProcessor{
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)throwsBeansException;
}
并且针对配置的 BeanFactoryPostProcessor 而言,因为获取顺序的不确定性,所以 Spring 支持对其配置优先级,上述方法的逻辑也可以看出 Spring 会依次处理 PriorityOrdered、Ordered,以及其他类型,并会针对各类型进行按照比较器进行排序处理。
6. 注册 BeanPostProcessor 后置处理器
不同于 BeanFactoryPostProcessor 的调用,这里仅仅是对 BeanPostProcessor 的注册,因为 BeanPostProcessor 作用于 bean 实例之上,而当前还没有开始创建 bean 实例,之前讲解 getBean 过程的文章中我们应该有所记忆,BeanPostProcessor 的调用是发生在 getBean 过程中,具体来说应该是围绕 bean 实例化过程的前后:
public interface BeanPostProcessor{
ObjectpostProcessBeforeInitialization(Object bean, String beanName)throwsBeansException;
ObjectpostProcessAfterInitialization(Object bean, String beanName)throwsBeansException;
}
注册过程本质上是将配置的 BeanPostProcessor 添加到 beanPostProcessors 集合的过程,我们在简单容器中需要通过调用 addBeanPostProcessor 编码注册我们实现的 BeanPostProcessor,实际上两者本质上是一样的,只是高级容器支持以配置的方式来完成简单容器中需要编码才能完成的操作:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 获取配置的 BeanPostProcessor 类型
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 注册一个 BeanPostProcessorChecker,用于在出现还没有注册后置处理器就开始实例化bean的情况打印日志记录
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>(); // 存放实现了 PriorityOrdered 接口的 BeanPostProcessor
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>(); // 存放 MergedBeanDefinitionPostProcessor
List<String> orderedPostProcessorNames = new ArrayList<String>(); // 存放实现了 Ordered 接口的 BeanPostProcessor
List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); // 存放其它的 BeanPostProcessor
// 遍历分类
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);
}
}
// 1.注册实现了 PriorityOrdered 接口的 BeanPostProcessor,不包含 MergedBeanDefinitionPostProcessor
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 2.注册实现了 Ordered 接口的 BeanPostProcessor
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(beanFactory, orderedPostProcessors);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// 3.注册其余的除 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor
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);
// 4.注册所有的 MergedBeanDefinitionPostProcessor
sortPostProcessors(beanFactory, internalPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 重新注册 ApplicationListenerDetector,将其移到链尾
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
BeanPostProcessor 与 BeanFactoryPostProcessor 一样,同样支持优先级的配置。
7. 初始化国际化资源
笔者目前所负责的几个项目都需要考虑国际化支持,有的直接基于 jdk 原生的 ResourceBundle,有的则基于 Spring 提供的 MessageSource,在具体分析 MessageSource 的初始化过程之前,我们先来了解一下 Spring 国际化支持的设计与简单使用。
7.1 MessageSource 的设计与简单使用
Spring MessageSource 支持本质上也是对 ResourceBundle 的封装,MessageSource 接口的定义如下:
public interface MessageSource{
/**
* 获取指定语言的文案信息
* code 为属性名称,args 用于传递格式化参数,defaultMessage 表示在找不到指定属性时返回的默认信息,locale 表示本地化对象
*/
StringgetMessage(String code, Object[] args, String defaultMessage, Locale locale);
/**
* 获取指定语言的文案信息
* 相对于第一个方法的区别在于当找不到对应属性时直接抛出异常
*/
StringgetMessage(String code, Object[] args, Locale locale)throwsNoSuchMessageException;
/**
* 获取指定语言的文案信息
* 只不过采用 MessageSourceResolvable 来封装第一个方法中的前三个参数
*/
StringgetMessage(MessageSourceResolvable resolvable, Locale locale)throwsNoSuchMessageException;
}
Spring MessageSource 相关类的继承关系如下:
其中 HierarchicalMessageSource 的设计为 MessageSource 提供了层次支持,建立了父子层级结构。ResourceBundleMessageSource 和 ReloadableResourceBundleMessageSource 是我们常用的两个类,均可以看做是对 jdk 原生国际化支持的封装,只不过后者相对于前者提供了定时更新资源文件的支持,从而不需要重启系统。StaticMessageSource 为编码式资源注册提供了支持,DelegatingMessageSource 则可以看做是 MessageSource 的一个代理,必要时对 MessageSource 进行封装。
下面我们演示一下 MessageSource 的简单使用,首先我们定义好国际化资源 resource.properties:
resource.properties
spring=Spring framework is a good design, the latest version is {0}
resource_zh.properties
spring=Spring 框架設計精良,當前最新版本是 {0}
resource_zh_CN.properties
spring=Spring 框架设计精良,当前最新版本是 {0}
需要注意的是,如果资源文件包含了非 ASCII 字符,则需要将文本内容转换成 Unicode 编码,jdk 自带的 native2ascii 工具可以达到目的,操作如下:
native2ascii -encoding utf-8 resource_zh.properties resource_zh_tmp.properties
然后我们在配置文件中进行如下配置:
<!--推荐以 messageResource 作为 id-->
<beanid="messageResource"class="org.springframework.context.support.ResourceBundleMessageSource">
<propertyname="basenames">
<list>
<value>i18n/resource</value>
</list>
</property>
</bean>
调用方式如下:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-core.xml");
Object[] params = {"4.3.8.RELEASE"};
System.out.println(context.getMessage("spring", params, Locale.ENGLISH));
System.out.println(context.getMessage("spring", params, Locale.TRADITIONAL_CHINESE));
System.out.println(context.getMessage("spring", params, Locale.SIMPLIFIED_CHINESE));
因为 ApplicationContext 同样实现了 MessageSource 接口,所以可以直接调用,但是这样调用的前提是配置中的 id 必须设置为 messageResource。输出如下:
Spring framework is a good design, the latest version is 4.3.8.RELEASE
Spring 框架設計精良,當前最新版本是 4.3.8.RELEASE
Spring 框架设计精良,当前最新版本是 4.3.8.RELEASE
7.2 MessageSource 的初始化过程
protected void initMessageSource(){
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
/*如果存在名称为 messageSource 的 bean*/
// 初始化资源
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// 构造层次关系
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
hms.setParentMessageSource(this.getInternalParentMessageSource());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using MessageSource [" + this.messageSource + "]");
}
} else {
/*不存在名称为 messageSource 的 bean*/
// 创建一个 DelegatingMessageSource 对象
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(this.getInternalParentMessageSource());
this.messageSource = dms;
// 以 messageSource 进行注册
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 + "]");
}
}
}
前面我们在配置时推荐将 id 配置为 messageSource 是有原因的,通过阅读源码则一目了然,代码中硬编码要求我们的配置 messageSource 作为 bean 的名称,否则不执行初始化,而是创建一个默认的代理,如果我们利用 ApplicationContext 对象去获取对应的资源则会出现异常,否则我们就需要手动指定 getBean 时候的名称,但是这样做是不推荐的,既然框架以约定的方式提供了相应的实现,还是推荐以 messageSource 作为 id 进行配置。
8. 初始化事件广播器
事件广播和监听机制是典型的观察者模式的实现,而 ApplicationEventMulticaster 也是观察者模式中主题角色的典型实现。在 Spring 中,如果我们希望监听事件广播器广播的事件,则需要定义一个实现了 ApplicationListener 接口的监听器,Spring 支持监听器的编码注册和自动扫描注册,这个我们在后面小节中细说,我们先来看一下这里广播器的初始化过程:
protected void initApplicationEventMulticaster(){
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
/*包含名称为 applicationEventMulticaster 的 bean*/
this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {
/*不包含名称为 applicationEventMulticaster 的 bean*/
// 创建并注册一个 SimpleApplicationEventMulticaster
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,进入该广播器的实现我们会发现如下逻辑:
public void multicastEvent(finalApplicationEvent event, ResolvableType eventType){
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : this.getApplicationListeners(event, type)) {
Executor executor = this.getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run(){
invokeListener(listener, event);
}
});
} else {
// 回调各个监听器
this.invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener listener, ApplicationEvent event){
ErrorHandler errorHandler = this.getErrorHandler();
if (errorHandler != null) {
try {
// 回调监听的监听方法 onApplicationEvent
listener.onApplicationEvent(event);
} catch (Throwable err) {
errorHandler.handleError(err);
}
} else {
try {
// 回调监听的监听方法 onApplicationEvent
listener.onApplicationEvent(event);
} catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || msg.startsWith(event.getClass().getName())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
} else {
throw ex;
}
}
}
}
典型的回调观察者监听方法的逻辑,如果对于观察者模式了解的话,这里的逻辑会比较好理解。
9. 注册事件监听器
既然有被观察者,就应该有观察者,事件监听器就是我们的观察者,我们需要将其注册来监听事件消息,针对事件监听器的注册,我们可以以编码的方式进行注册,如果我们将其配置到配置文件中,容器也会自动扫描进行注册:
protected void registerListeners(){
// 1.注册所有的编码添加的事件监听器
for (ApplicationListener<?> listener : this.getApplicationListeners()) {
this.getApplicationEventMulticaster().addApplicationListener(listener);
}
// 2. 扫描注册以配置方式添加的事件监听器(延迟加载)
String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 3. 发布需要提前广播的事件
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
// 通知事件
this.getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
10. 实例化所有非延迟加载的单例
记得最开始学习 Spring 框架的时候,就看到说 BeanFactory 和 ApplicationContext 有一个很大的区别就是 BeanFactory 在初始化容器时不会实例化 bean,而 ApplicationContext 则会实例化所有非延迟加载的单例 bean,而这个加载过程就在这里发生。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory){
// 如果存在类型转换器,则进行加载
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));
}
// 如果不存在 embedded value resolver 则设置一个默认的
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
@Override
publicStringresolveStringValue(String strVal){
return getEnvironment().resolvePlaceholders(strVal);
}
});
}
// AOP支持,实例化 LoadTimeWeaverAware
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
this.getBean(weaverAwareName);
}
beanFactory.setTempClassLoader(null);
// 冻结所有 bean 的定义,不再允许更改
beanFactory.freezeConfiguration();
// 实例化所有的非延迟加载的bean(非abstract && 单例 && 非延迟加载)
beanFactory.preInstantiateSingletons();
}
由上述逻辑可以看到在执行实例化操作之前,容器会先校验一些必要的工具实例,如果之前没有注册则会创建一个默认的代替,然后会冻结所有的 bean 定义,毕竟即将开始实例化,后续的更改也不会再生效。在一些准备工作完毕之后,容器即开始实例化所有满足条件(非abstract && 单例 && 非延迟加载)的 bean。
Spring 4.1 增加了 SmartInitializingSingleton,实现了该接口的单例可以感知所有单例实例化完成的事件,而接口中声明的方法 afterSingletonsInstantiated 也在这里被回调:
public void preInstantiateSingletons()throwsBeansException{
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// 遍历实例化满足条件的 bean
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = this.getMergedLocalBeanDefinition(beanName);
// 不是abstract && 单例 && 不是延迟加载的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (this.isFactoryBean(beanName)) {
// 工厂bean
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
publicBooleanrun(){
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
this.getBean(beanName);
}
} else {
// 普通单例
this.getBean(beanName);
}
}
}
// 4.1版本新特性 SmartInitializingSingleton
for (String beanName : beanNames) {
Object singletonInstance = this.getSingleton(beanName);
// SmartInitializingSingleton 类型
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
publicObjectrun(){
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
11. 完成刷新过程,发布应用事件
Spring 很早就提供了 Lifecycle 接口,实现了该接口的 bean 可以感知到容器的启动和关闭状态,对应着接口的 start 和 stop 方法,而 start 方法的回调则位于这个时候发生:
protected void finishRefresh(){
// 初始化 LifecycleProcessor
this.initLifecycleProcessor();
// 调用所有实现了 Lifecycle 的 start 方法
this.getLifecycleProcessor().onRefresh();
// 发布上下文刷新完毕事件
this.publishEvent(new ContextRefreshedEvent(this));
// 注册到 LiveBeansView MBean
LiveBeansView.registerApplicationContext(this);
}
Lifecycle 对应方法的执行需要依赖于 LifecycleProcessor,我们可以自定义 LifecycleProcessor,否则容器会创建一个默认的 DefaultLifecycleProcessor,然后基于定义的 LifecycleProcessor 来调用满足条件 bean 的 start 方法。在完成了这一操作之后,容器的初始化过程基本上完成,这个时候容器可以将容器刷新完毕事件通知到对应的监听器。
到这里,高级容器的初始化过程我们已经探究完了,不同于 BeanFactory 在该阶段仅仅是将静态配置转换成容器中对应的 BeanDefinition 实例,ApplicationContext 因为需要实例化所有非延迟加载的单例,所以此时大部分的 bean 已经以实例的形式存在,后续我们再 getBean 也仅仅是针对非单例 bean 才需要执行复杂的实例化操作,所以在高级容器中本篇文章所探究的过程基本可以概括容器的大部分工作。
针对 Spring IoC 相关源码的探究,到这里就结束了,鉴于作者水平有限,文章中不免有错误之处,欢迎大家的指正,后续针对 IoC 有新的认识和见解,我也会回来更正和完善本系列的文章。鉴于最近项目繁重,Spring 源码的阅读解析工作暂告一段落,下次回归时我们来继续探究 AOP 的源码解析。
如果你觉得这篇文章对你有帮助 点赞关注,然后私信回复【888】即可免费获取Java进阶全套视频以及源码学习资料
相关推荐
- “版本末期”了?下周平衡补丁!国服最强5套牌!上分首选
-
明天,酒馆战棋就将迎来大更新,也聊了很多天战棋相关的内容了,趁此机会,给兄弟们穿插一篇构筑模式的卡组推荐!老规矩,我们先来看10职业胜率。目前10职业胜率排名与一周前基本类似,没有太多的变化。平衡补丁...
- VS2017 C++ 程序报错“error C2065:“M_PI”: 未声明的标识符"
-
首先,程序中头文件的选择,要选择头文件,在文件中是没有对M_PI的定义的。选择:项目——>”XXX属性"——>配置属性——>C/C++——>预处理器——>预处理器定义,...
- 东营交警实名曝光一批酒驾人员名单 88人受处罚
-
齐鲁网·闪电新闻5月24日讯酒后驾驶是对自己和他人生命安全极不负责的行为,为守护大家的平安出行路,东营交警一直将酒驾作为重点打击对象。5月23日,东营交警公布最新一批饮酒、醉酒名单。对以下驾驶人醉酒...
- Qt界面——搭配QCustomPlot(qt platform)
-
这是我第一个使用QCustomPlot控件的上位机,通过串口精确的5ms发送一次数据,再将读取的数据绘制到图表中。界面方面,尝试卡片式设计,外加QSS简单的配了个色。QCustomPlot官网:Qt...
- 大话西游2分享赢取种族坐骑手办!PK趣闻录由你书写
-
老友相聚,仗剑江湖!《大话西游2》2021全民PK季4月激燃打响,各PK玩法鏖战齐开,零门槛参与热情高涨。PK季期间,不仅各种玩法奖励丰厚,参与PK趣闻录活动,投稿自己在PK季遇到的趣事,还有机会带走...
- 测试谷歌VS Code AI 编程插件 Gemini Code Assist
-
用ClaudeSonnet3.7的天气测试编码,让谷歌VSCodeAI编程插件GeminiCodeAssist自动编程。生成的文件在浏览器中的效果如下:(附源代码)VSCode...
- 顾爷想知道第4.5期 国服便利性到底需优化啥?
-
前段时间DNF国服推出了名为“阿拉德B计划”的系列改版计划,截至目前我们已经看到了两项实装。不过关于便利性上,国服似乎还有很多路要走。自从顾爷回归DNF以来,几乎每天都在跟我抱怨关于DNF里面各种各样...
- 掌握Visual Studio项目配置【基础篇】
-
1.前言VisualStudio是Windows上最常用的C++集成开发环境之一,简称VS。VS功能十分强大,对应的,其配置系统较为复杂。不管是对于初学者还是有一定开发经验的开发者来说,捋清楚VS...
- 还嫌LED驱动设计套路深?那就来看看这篇文章吧
-
随着LED在各个领域的不同应用需求,LED驱动电路也在不断进步和发展。本文从LED的特性入手,推导出适合LED的电源驱动类型,再进一步介绍各类LED驱动设计。设计必读:LED四个关键特性特性一:非线...
- Visual Studio Community 2022(VS2022)安装图文方法
-
直接上步骤:1,首先可以下载安装一个VisualStudio安装器,叫做VisualStudioinstaller。这个安装文件很小,很快就安装完成了。2,打开VisualStudioins...
- Qt添加MSVC构建套件的方法(qt添加c++11)
-
前言有些时候,在Windows下因为某些需求需要使用MSVC编译器对程序进行编译,假设我们安装Qt的时候又只是安装了MingW构建套件,那么此时我们该如何给现有的Qt添加一个MSVC构建套件呢?本文以...
- Qt为什么站稳c++GUI的top1(qt c)
-
为什么现在QT越来越成为c++界面编程的第一选择,从事QT编程多年,在这之前做C++界面都是基于MFC。当时为什么会从MFC转到QT?主要原因是MFC开发界面想做得好看一些十分困难,引用第三方基于MF...
- qt开发IDE应该选择VS还是qt creator
-
如果一个公司选择了qt来开发自己的产品,在面临IDE的选择时会出现vs或者qtcreator,选择qt的IDE需要结合产品需求、部署平台、项目定位、程序猿本身和公司战略,因为大的软件产品需要明确IDE...
- Qt 5.14.2超详细安装教程,不会来打我
-
Qt简介Qt(官方发音[kju:t],音同cute)是一个跨平台的C++开库,主要用来开发图形用户界面(GraphicalUserInterface,GUI)程序。Qt是纯C++开...
- Cygwin配置与使用(四)——VI字体和颜色的配置
-
简介:VI的操作模式,基本上VI可以分为三种状态,分别是命令模式(commandmode)、插入模式(Insertmode)和底行模式(lastlinemode),各模式的功能区分如下:1)...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- “版本末期”了?下周平衡补丁!国服最强5套牌!上分首选
- VS2017 C++ 程序报错“error C2065:“M_PI”: 未声明的标识符"
- 东营交警实名曝光一批酒驾人员名单 88人受处罚
- Qt界面——搭配QCustomPlot(qt platform)
- 大话西游2分享赢取种族坐骑手办!PK趣闻录由你书写
- 测试谷歌VS Code AI 编程插件 Gemini Code Assist
- 顾爷想知道第4.5期 国服便利性到底需优化啥?
- 掌握Visual Studio项目配置【基础篇】
- 还嫌LED驱动设计套路深?那就来看看这篇文章吧
- Visual Studio Community 2022(VS2022)安装图文方法
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)