Spring - SmartInitializingSingleton扩展接口
Posted 小小工匠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring - SmartInitializingSingleton扩展接口相关的知识,希望对你有一定的参考价值。
文章目录
Pre
org.springframework.beans.factory.SmartInitializingSingleton
public interface SmartInitializingSingleton
/**
* Invoked right at the end of the singleton pre-instantiation phase,
* with a guarantee that all regular singleton beans have been created
* already. @link ListableBeanFactory#getBeansOfType calls within
* this method won't trigger accidental side effects during bootstrap.
* <p><b>NOTE:</b> This callback won't be triggered for singleton beans
* lazily initialized on demand after @link BeanFactory bootstrap,
* and not for any other bean scope either. Carefully use it for beans
* with the intended bootstrap semantics only.
*/
void afterSingletonsInstantiated();
触发时机
只有一个方法afterSingletonsInstantiated
,其作用是是 在spring容器管理的所有单例对象(非懒加载对象)初始化完成之后调用的回调接口。
其触发时机为postProcessAfterInitialization
之后。
使用场景
可以扩展此接口在对所有单例对象初始化完毕后,做一些后置的业务处理
源码解析
org.springframework.context.support.AbstractApplicationContext#refresh
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
smartSingleton.afterSingletonsInstantiated();
在Spring容器启动时,会调用方法refresh()
;
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
/**
* 做一些前期准备工作
* 1、为子类提供抽模板方法initPropertySources:子类可以把ServletContext中的参数对设置到Environment
* 2、校验环境变量属性
* 3、初始化earlyApplicationListeners
* 4、初始化earlyApplicationEvents
*/
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/**
* 为子类提供refreshBeanFactory()方法,子类可以对BeanFactory进行一些操作与设置
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
/**
* 准备BeanFactory
* 1. 设置BeanFactory的类加载器BeanClassLoader、SpringEL表达式解析器beanExpressionResolver、类型转化注册器PropertyEditorRegistrar
* 2. 添加三个BeanPostProcessor,注意是具体的BeanPostProcessor实例对象
* 2.1、ApplicationContextAwareProcessor:用来处理EnvironmentAware、EmbeddedValueResolverAware等回调setApplicationContext()方法
* 2.2、ApplicationListenerDetector:负责把实现了ApplicantsListener类型的Bean注册到ApplicationContext的监听列表
* 2.3、LoadTimeWeaverAwareProcessor:
*
* 3. 记录ignoreDependencyInterface:如果一个属性对应的set方法在ignoredDependencyInterfaces接口中被定义了,则该属性不会被spring进行自动注入
* EnvironmentAware
* EmbeddedValueResolverAware
* ResourceLoaderAware
* ApplicationEventPublisherAware
* MessageSourceAware
* ApplicationContextAware
* ApplicationStartupAware
*
* 4. 记录ResolvableDependency
* BeanFactory
* ResourceLoader
* ApplicationEventPublisher
* ApplicationContext
*
* 5. 添加四个环境相关的单例Bean
* 5.1、environment
* 5.2、systemProperties
* 5.3、systemEnvironment
* 5.4、applicationStartup
*/
prepareBeanFactory(beanFactory);
try
// Allows post-processing of the bean factory in context subclasses.
/**
* 为子类提供的方法,子类可以对BeanFactory进行设置
* 此方法允许子类在所有的bean尚未初始化之前注册BeanPostProcessor。
* 通过XML和注解初始化无默认实现,
* 如果是WEB容器则此步会进行web容器scope(request、session、application)的注册和注册环境相关的bean等操作
*/
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
/**
* 执行所有的BeanFactoryPostProcessor,包括自定义的和spring内置的,开始对BeanFactory进行处理
* 在此步骤内会将所有的bean对应的BeanDefinition解析出来放入到beanFactory的BeanDefinitionMap中
* 默认情况下,
* BeanFactory中的BeanDefinitionMap中有6个BeanDefinition,5个基础的+配置类AppConfig
* 这6个中有一个BeanFactoryPostProcessor:ConfigurationClassPostProcessor,这个类主要是解析配置类,
* 配置类:1、加了 @Configuration注解的Full配置类
* 2、加了 @Component,@ComponentScan,@Import,@ImportResource,@Bean 注解的 Lite配置类
* 扫描的过程中可能又会扫描出其他的BeanFactoryPostProcessor,那么这些BeanFactoryPostProcessor也得在这一步执行
*
*
* BeanFactoryPostProcessors按入场方式分为:
* 1. 程序员调用ApplicationContext的API手动添加
* 2. Spring自己扫描出来的
*
* BeanFactoryPostProcessor按类型又可以分为:
* 1. 普通BeanFactoryPostProcessor
* 2. BeanDefinitionRegistryPostProcessor
*
* 执行顺序顺序如下:
* 1. 执行手动添加的BeanDefinitionRegistryPostProcessor 的postProcessBeanDefinitionRegistry()方法
* 2. 执行扫描出来的BeanDefinitionRegistryPostProcessor + 实现了PriorityOrdered 的postProcessBeanDefinitionRegistry()方法
* 3. 执行扫描出来的BeanDefinitionRegistryPostProcessor + 实现了Ordered 的postProcessBeanDefinitionRegistry()方法
* 4. 执行扫描出来的BeanDefinitionRegistryPostProcessor + 普通 的postProcessBeanDefinitionRegistry()方法
* 5. 执行扫描出来的BeanDefinitionRegistryPostProcessor + 所有 的postProcessBeanFactory()方法
* 6. 执行手动添加的BeanFactoryPostProcessor 的postProcessBeanFactory()方法
* 7. 执行扫描出来的BeanFactoryPostProcessor + 实现了PriorityOrdered 的postProcessBeanFactory()方法
* 8. 执行扫描出来的BeanFactoryPostProcessor + 实现了Ordered 的postProcessBeanFactory()方法
* 9. 执行扫描出来的BeanFactoryPostProcessor + 普通 的postProcessBeanFactory()方法
*
* ConfigurationClassPostProcessor就会在第2步执行,会进行扫描
*/
invokeBeanFactoryPostProcessors(beanFactory);
/**
* 扫描BeanPostProcessor实例化并排序,并添加到BeanFactory中的beanPostProcessor中
* 之前已经注册过三个
* 在这一步实例化BeanPostProcessor是因为BeanPostProcessor是用来干预bean的创建过程的,后面要实例化bean了,所以需要提前把所有的BeanPostProcessor实例化出来
*
* 扫描BeanPostProcessor顺序如下:
* 1、注册: PostProcessorRegistrationDelegate.BeanPostProcessorChecker
* 2、扫描并注册:实现PriorityOrdered接口的
* 3、扫描并注册:实现Ordered接口的
* 4、扫描并注册:未排序的
* 5、扫描并注册:MergedBeanDefinitionPostProcessor的
* 6、注册:ApplicationListenerDetector
*/
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
// 设置ApplicationContext的MessageSource,要么是用户设置的,要么是DelegatingMessageSource
initMessageSource();
/**
* 初始化事件广播,作用是:发布事件,并且为所发布的事件找到对应的事件监听器。
* 设置ApplicationContext的applicationEventMulticaster,要么是用户设置的,要么是SimpleApplicationEventMulticaster
*/
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 给子类的模板方法,执行其他的初始化操作,如和SpringMVC整合时,需要初始化一些其他的bean,默认是一个空方法
onRefresh();
// 把定义的ApplicationListener的Bean对象,设置到ApplicationContext中去,并执行在此之前所发布的事件
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化其余的非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
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.
destroyBeans();
// Reset 'active' flag.
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...
resetCommonCaches();
contextRefresh.end();
重点看 finishBeanFactoryInitialization
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
// ....
try
// ....
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// ....
catch (BeansException ex)
// ....
finally
// ....
继续
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)
// ...
// 实例化非懒加载的单例Bean
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
继续
@Override
public void preInstantiateSingletons() throws BeansException
// ....
// 所有的非懒加载单例Bean都创建完了后
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames)
Object singletonInstance = getSingleton(beanName);
// 如果实例实现了SmartInitializingSingleton,执行afterSingletonsInstantiated方法。
if (singletonInstance instanceof SmartInitializingSingleton)
// ....
// 所有的非懒加载单例bean都创建完成之后调用
smartSingleton.afterSingletonsInstantiated();
扩展示例
package com.artisan.bootspringextend.testextends;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.annotation.Configuration;
/**
* @author 小工匠
* @version 1.0
* @description: TODO
* @date 2022/12/6 23:23
* @mark: show me the code , change the world
*/
@Slf4j
@Configuration
public class ExtendSmartInitializingSingleton implements SmartInitializingSingleton
@Override
public void afterSingletonsInstantiated()
log.info("----->ExtendSmartInitializingSingleton#afterSingletonsInstantiated called");
以上是关于Spring - SmartInitializingSingleton扩展接口的主要内容,如果未能解决你的问题,请参考以下文章
Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC
学习笔记——Spring简介;Spring搭建步骤;Spring的特性;Spring中getBean三种方式;Spring中的标签
Spring框架--Spring事务管理和Spring事务传播行为