在查看 Application
的refresh
方法中,最后实例化所有的bean,其中单独处理了SmartInitializingSingleton
,记录下。
一、源码相关
// DefaultListableBeanFactory
// 确保所有非延迟初始单例都实例化。
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("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<>(this.beanDefinitionNames);
// 遍历进行非延迟的单利的 bean 的实例化
// 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)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// 实例化完成后,再进行遍历,判断是不是 SmartInitializingSingleton 的实现,然后调用实现的方法
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
根据源码查看就是所有的非延迟的单利的 bean 初始化完成以后,在调用所有实现 SmartInitializingSingleton
的 bean 所实现的方法。
二、接口简介
- 接口定义
// 类中只有一个方法,需要实现类实现
public interface SmartInitializingSingleton {
void afterSingletonsInstantiated();
}
- 接口文档
BeanFactory 启动过程中,在非延迟的、单例的bean 实例化阶段结束时触发了回调接口。
该接口可以由单例的bean实现,以便在常规的单例实例化之后执行一些初始化,避免意外的早期初始化带来的副作用(例如,来自ListableBeanFactory.getBeansOfType
调用)。 从这个意义上讲,它是InitializingBean
的替代方法,后者在Bean的本地构造阶段结束时立即触发。
这个回调有点类似于org.springframework.context.event.ContextRefreshedEvent
但是不需要实现org.springframework.context.ApplicationListener
,不需要过滤整个上下文层次结构中的上下文引用。对beans包的依赖性最小,并且由独立的ListableBeanFactory
实现兑现,而不仅仅是在org.springframework.context.ApplicationContext
环境中。
注意:如果要启动/管理异步任务,则最好实现org.springframework.context.Lifecycle
,它为运行时管理提供了更丰富的模型,并允许分阶段启动/关闭。
所以这个接口的特点:
1、实现的bean 必须是单例的
2、在非延迟单例的bean实例化之后调用,避免一些提前初始化的副作用
三、SmartInitializingSingleton 和 InitializingBean的区别
InitializingBean
是在每一个bean 初始化完成后调用;多例的情况下每初始化一次就掉用一次。
SmartInitializingSingleton
是所有的非延迟的、单例的bean 都初始化后调用,只调用一次。如果是多例的bean实现,不会调用。
四、测试
InitializingBean
、@PostConstruct
、BeanPostProcessor
、SmartInitializingSingleton
测试执行顺序与执行次数。
BeanPostProcessor 接口
定义两个实现了InitializingBean
的非延迟的单例bean,并且类中增加了@PostConstruct
注解的初始化方法.InitializingBeanImplTest
的优先级高。
定义一个实现了BeanPostProcessor
的bean;
定义一个实现了SmartInitializingSingleton
的非延迟的单例bean。
// InitializingBeanImplTest
@Component
@Order(Ordered.LOWEST_PRECEDENCE - 1000)
public class InitializingBeanImplTest implements InitializingBean {
// 构造函数
public InitializingBeanImplTest() {
System.out.println(InitializingBeanImplTest.class.getSimpleName() + "#Constructor");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(InitializingBeanImplTest.class.getSimpleName() + " :: " + InitializingBean.class.getSimpleName() + "#afterPropertiesSet");
}
@PostConstruct
public void init() {
System.out.println(InitializingBeanImplTest.class.getSimpleName() + " :: " + PostConstruct.class.getSimpleName());
}
}
// InitializingBeanImplTest02
@Component
public class InitializingBeanImplTest02 implements InitializingBean {
// 构造函数
public InitializingBeanImplTest02() {
System.out.println(this.getClass().getSimpleName() + "#Constructor");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(this.getClass().getSimpleName() + " :: " + InitializingBean.class.getSimpleName() + "#afterPropertiesSet");
}
@PostConstruct
public void init() {
System.out.println(this.getClass().getSimpleName() + " :: " + PostConstruct.class.getSimpleName());
}
}
// BeanPostProcessorImplTest
@Component
public class BeanPostProcessorImplTest implements BeanPostProcessor, PriorityOrdered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (check(bean))
System.out.println(BeanPostProcessorImplTest.class.getSimpleName() + " :: " + bean.getClass().getSimpleName() + "#postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (check(bean))
System.out.println(BeanPostProcessorImplTest.class.getSimpleName() + " :: " + bean.getClass().getSimpleName() + "#postProcessAfterInitialization");
return bean;
}
private boolean check(Object bean) {
return bean instanceof InitializingBeanImplTest || bean instanceof InitializingBeanImplTest02;
}
@Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
}
// SmartInitializingSingletonTest
@Component
public class SmartInitializingSingletonTest implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println(SmartInitializingSingletonTest.class.getSimpleName() + "#afterSingletonsInstantiated");
}
}
输出:
可以看出执行顺序:
1、InitializingBeanImplTest
的构造函数;
2、BeanPostProcessor
的postProcessBeforeInitialization
实现方法;
3、InitializingBeanImplTest
的@PostConstruct
注解的方法;
4、InitializingBeanImplTest
实现的InitializingBean
中的afterPropertiesSet
方法
5、BeanPostProcessor
的postProcessAfterInitialization
实现方法;
到这里是InitializingBeanImplTest
实例化完成,随后执行InitializingBeanImplTest02
的实例化,先后顺序与此相同。
最后,当两个bean都实例化完成后,调用了SmartInitializingSingletonTest
实现的SmartInitializingSingleton
的afterSingletonsInstantiated
方法。
更改SmartInitializingSingletonTest
,添加注解@Scope(BeanDefinition.SCOPE_PROTOTYPE)
变成多例。SmartInitializingSingletonTest
不在执行回掉了。
五、总结
1、实现SmartInitializingSingleton
的bean 要是单例
2、在所有非延迟的单例的bean初始化完成后调用。