SpringBoot源码解读与原理分析(二十)IOC容器的刷新(一)
SpringBoot源码解读与原理分析(二十一)IOC容器的刷新(二)
SpringBoot源码解读与原理分析(二十二)IOC容器的刷新(三)ConfigurationClassPostProcessor
SpringBoot源码解读与原理分析(二十三)IOC容器的刷新(四)
SpringBoot源码解读与原理分析(二十四)IOC容器的刷新(五)
这一节继续梳理第十二步和第十三步(7.12-7.13),并总结一下IOC容器刷新过程中涉及的扩展点。
代码清单1:AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 7.1 初始化前的预处理
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 7.2 获取BeanFactory,加载所有bean的定义信息(未实例化)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 7.3 BeanFactory的预处理配置
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 7.4 BeanFactory准备工作完成后的后置处理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 7.5 BeanFactory创建后的后置处理器的执行
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 7.6 初始化Bean的后置处理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 7.7 初始化MessageSource
initMessageSource();
// Initialize event multicaster for this context.
// 7.8 初始化事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 7.9 子类扩展的刷新动作
onRefresh();
// Check for listener beans and register them.
// 7.10 注册监听器
registerListeners();
// 至此,BeanFactory创建完成
// Instantiate all remaining (non-lazy-init) singletons.
// 7.11 初始化所有剩下的单实例bean对象
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 7.12 刷新后的动作
finishRefresh();
} // catch ...
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
// 7.13 清理缓存
resetCommonCaches();
}
}
}
// 7.12 刷新后的动作
finishRefresh();
代码清单2:AbstractApplicationContext.java
protected void finishRefresh() {
// 清除上下文级的资源缓存(例如扫描的ASM言数据)
clearResourceCaches();
// 初始化生命周期处理器
initLifecycleProcessor();
// 回调LifecycleProcessor的刷新动作
getLifecycleProcessor().onRefresh();
// 发布容器刷新完成的事件,触发特定监听器
publishEvent(new ContextRefreshedEvent(this));
LiveBeansView.registerApplicationContext(this);
}
在 SpringBoot源码解读与原理分析(二十四)IOC容器的刷新(五) 7.11.3.2 doCreateBean 5.bean对象的初始化 中提到,在initializeBean
方法中会执行init-method、@PostConstruct等扩展点。
这一步的finishRefresh
方法通过Lifecycle接口为bean对象提供了新的生命周期回调切入时机,可以在IOC容器的启动、停止时自动触发Lifecycle接口中的start
方法和stop
方法。
代码清单3:AbstractApplicationContext.java
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
// logger ...
} else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
// logger ...
}
}
由 代码清单3 可知,默认的LifecycleProcessor实现类是DefaultLifecycleProcessor。
代码清单4:DefaultLifecycleProcessor.java
@Override
public void onRefresh() {
startBeans(true);
this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, DefaultLifecycleProcessor.LifecycleGroup> phases = new HashMap<>();
lifecycleBeans.forEach((beanName, bean) -> {
// 由于autoStartupOnly=true,所以这一段不会执行
// 如果bean对象实现了SmartLifecycle接口且isAutoStartup方法的返回值为true,执行
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
DefaultLifecycleProcessor.LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new DefaultLifecycleProcessor.LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(beanName, bean);
}
});
// 由于上面代码没有执行,phases依旧为空,所以不会执行start方法
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
由 代码清单4 可知,由于startBeans(true)
方法的参数为true,所以lifecycleBeans.forEach不会执行,phases始终为空,不会回调Lifecycle接口的start
方法。
如果要回调Lifecycle接口的start
方法,需要显式调用ApplicationContext的start
方法。由于SpringBoot启动过程中没有回调start
方法,所以仅实现Lifecycle接口的bean对象不会被回调。
如果需要在IOC容器刷新阶段自动回调start
方法,bean对象需要实现SmartLifecycle接口且isAutoStartup方法的返回值为true(默认返回true)。
// 7.13 清理缓存
resetCommonCaches();
代码清单5:AbstractApplicationContext.java
protected void resetCommonCaches() {
ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
}
由 代码清单5 可知,IOC容器刷新的最后一步会清楚整个IOC容器刷新期间的缓存。
至此,IOC容器的刷新全部完成。
在IOC容器的初始化逻辑中由许多的扩展点可供开发者切入利用。
在refresh
方法中,第一个可切入的扩展点是第五步的invokeBeanFactoryPostProcessors
方法,即BeanFactory创建后的后置处理器的执行。
第一个扩展点是ImportSelector和ImportBeanDefinitionRegistrar接口。
在 SpringBoot源码解读与原理分析(二十二)IOC容器的刷新(三)ConfigurationClassPostProcessor 7.5.7.3 ConfigurationClassParser的parse方法 中提到,ConfigurationClassPostProcessor的执行过程中会解析@Import注解,提取出其中的ImportBeanDefinitionRegistrar并执行。
ImportSelector在该阶段只能获取当前@Import标注的注解配置类的信息,而ImportBeanDefinitionRegistrar在该阶段除了能获取当前@Import标注的注解配置类的信息,还能获取BeanDefinitionRegistrar,由此可见可供扩展的动作主要是给BeanDefinitionRegistrar中编程式注册新的BeanDefinition。
第二个扩展点是BeanDefinitionRegistryPostProcessor。它可以获取BeanDefinitionRegistry对象,利用该对象可以直接向IOC容器编程式注册新的BeanDefinition,以及移除容器中已有的BeanDefinition。
一般情况下,自定义的BeanDefinitionRegistryPostProcessor的执行时机比内置的ConfigurationClassPostProcessor要晚,因为ConfigurationClassPostProcessor实现了PriorityOrdered接口,这个接口的优先级最高。
特殊情况下,要使自定义的BeanDefinitionRegistryPostProcessor的执行时机比内置的ConfigurationClassPostProcessor更早,可以让自定义的BeanDefinitionRegistryPostProcessor也实现PriorityOrdered接口,则能达到目的。
第三个扩展点是BeanFactoryPostProcessor。它可以获取ConfigurableListableBeanFactory对象,可以获取和修改现有的BeanDefinition(原则上不能注册新的BeanDefinition)。
另外,BeanFactoryPostProcessor的处理阶段中允许提早初始化bean对象,但是这个阶段只有ApplicationContextAwareProcessor注册到了BeanFactory中,没有其余关键的BeanFactoryPostProcessor,因此这个阶段初始化的bean对象有一个共同的特点,可是使用Aware回调注入,但无法使用@Autowired等依赖注入的注解,且不会产生任何代理对象。
在refresh
方法中,第二个可切入的扩展点是第十一步的finishBeanFactoryInitialization
方法,即初始化非延迟加载的单实例bean对象。
MergedBeanDefinitionPostProcessor的postProcessBeforeInstantiation
方法使用在createBean
方法中的resolveBeforeInstantiation
方法中。
在bean对象实例化之前,InstantiationAwareBeanPostProcessor可以前置拦截bean对象的实例化动作,来代替真正的bean对象实例化逻辑。如果成功实例化了bean对象,则直接返回,否则执行真正的bean对象实例化流程。
SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors
方法使用在doCreateBean
方法中的createBeanInstance
方法中。
如果实例化之前InstantiationAwareBeanPostProcessor没有拦截成功,则会执行真正的bean对象实例化逻辑,通过构造方法实例化对象。如果一个bean对象的所属类型中定义了多个构造方法,那么选择哪一个构造方法,就是其中一个扩展点。
底层在筛选构造方法是,会获取所有SmartInstantiationAwareBeanPostProcessor,回调其determineCandidateConstructors
方法获取可选择的构造方法。
一般情况下,SmartInstantiationAwareBeanPostProcessor在SpringFramework内部未内置使用逻辑,了解即可。
MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition
方法使用在doCreateBean
方法中的applyMergedBeanDefinitionPostProcessors
方法中。
由于已经执行了doCreateBean
方法中的createBeanInstance
方法,此时bean对象已经实例化,但没有进行属性赋值和依赖注入。紧接着会回调所有的MergedBeanDefinitionPostProcessor,收集bean对象所属Class中的注解信息。
在 SpringBoot源码解读与原理分析(二十四)IOC容器的刷新(五) 7.11.3.2 doCreateBean 2.属性赋值前的注解信息收集 中已经列出了3个关键的MergedBeanDefinitionPostProcessor,分别是InitDestroyAnnotationBeanPostProcessor(收集@PostConstruct注解和@PostDestroy注解)、CommonAnnotationBeanPostProcessor(收集JSR-250规范中的注解,如@WebServiceRef、@EJB、 @Resource等)、AutowiredAnnotationBeanPostProcessor(收集@Autowired、@Value、@Inject注解)。
InstantiationAwareBeanPostProcessor的使用在doCreateBean
方法中的populateBean
方法中。
这个扩展点根据InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation
方法的返回值决定是否继续执行后续的populateBean
方法和initializeBean
方法初始化对象,起到流程控制的作用。
InstantiationAwareBeanPostProcessor的postProcessProperties
方法的使用是在doCreateBean
方法中的populateBean
方法中。
这个扩展点会将bean对象对应的PropertyValues中封装赋值和注入的属性和依赖对象实际应用到bean对象的实例中。
通常情况下,这一阶段起作用的后置处理器是AutowiredAnnotationBeanPostProcessor,它会收集bean对象所属的Class类型中标注了@Autowired、@Value等注解的属性和方法,并反射赋值/调用。
BeanPostProcessor的postProcessProperties
方法的使用是在doCreateBean
方法中的initializeBean
方法中。
属性赋值和依赖注入完成后,下一个核心步骤是initializeBean
方法,该方法包含BeanPostProcessor的前后两个执行动作postProcessBeforeInitialization
、postProcessAfterInitialization
,给已经完成属性赋值和依赖注入的bean对象添加一些额外的属性的赋值、回调以及生成代理对象等动作。
SmartInitializingSingleton的使用是在preInstantiateSingletons
方法中。
在所有非延迟加载的单实例bean对象全部初始化完成后,最后一个扩展点是SmartInitializingSingleton。它会提取出所有实现了SmartInitializingSingleton接口的bean对象,回调其afterSingletonsInstantiated
方法,这使得BeanFactory也有机会参与bean对象初始化完成后的扩展处理。
…
本节完,更多内容请查阅分类专栏:SpringBoot源码解读与原理分析