文档章节

Spring SmartInitializingSingleton

OrangeJoke
 OrangeJoke
发布于 05/15 11:46
字数 618
阅读 127
收藏 4

使用场景

我们在这样的场景下使用,当ApplicationContext 加载完所有的Bean之后,我们来做一些我们想要的操作。 下面是使用方法:

public class MyRegister implements SmartInitializingSingleton {
    Logger logger = LoggerFactory.getLogger(MyRegister.class);
    private final DefaultListableBeanFactory beanFactory;
    public MyRegister(DefaultListableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }
    @Override
    public void afterSingletonsInstantiated() {
        Map<String, Tiger> redisCacheProviderMap = beanFactory.getBeansOfType(Tiger.class);
        logger.info("tiger pre init");
    }
}

接口说明

/**
 *<p> Callback interface triggered at the end of the singleton pre-instantiation phase
 * during {@link BeanFactory} bootstrap.
 *
 * <p>This callback variant is somewhat similar to
 * {@link org.springframework.context.event.ContextRefreshedEvent} but doesn't
 * require an implementation of {@link org.springframework.context.ApplicationListener},
 * with no need to filter context references across a context hierarchy etc.
 * It also implies a more minimal dependency on just the {@code beans} package
 * and is being honored by standalone {@link ListableBeanFactory} implementations,
 * not just in an {@link org.springframework.context.ApplicationContext} environment.
 */
 public interface SmartInitializingSingleton {}

主要摘取上面一段说明来解答疑惑:

  1. 这个接口的功能类似ContextRefreshedEvent(由ConfiguableApplicationContext.refresh()触发),ContextRefreshedEvent的具体阶段来看下面具体文档。

Published when the ApplicationContext is initialized or refreshed (for example, by using the refresh() method on the ConfigurableApplicationContext interface). Here, “initialized” means that all beans are loaded, post-processor beans are detected and activated, singletons are pre-instantiated, and the ApplicationContext object is ready for use. As long as the context has not been closed, a refresh can be triggered multiple times, provided that the chosen ApplicationContext actually supports such “hot” refreshes. For example, XmlWebApplicationContext supports hot refreshes, but GenericApplicationContext does not.

对比接收事件的优点:就是不需要实现ApplicationListener,引用也更加简单(不需要获取ApplicationContext),对应性能也会更好一点。

  1. 文档里说到 pre-instantiation phase 这个比较疑惑,实际上这里的pre-instantiation对应SmartInitializingSingleton的执行过程·

public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {

	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
		// 省略其他步骤.........
		// Instantiate all remaining (non-lazy-init) singletons.
		finishBeanFactoryInitialization(beanFactory);
		// Last step: publish corresponding event.
		finishRefresh();
		}
}

finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)
{
  //省略其他步骤.......
  // Instantiate all remaining (non-lazy-init) singletons.
  beanFactory.preInstantiateSingletons();
}

所以结论就是SmartInitializingSingleton的方法就是在finishRefresh() 触发ContextRefreshedEvent事件前执行的。所以上面的pre-instantiation phase说的就是beanFactory.preInstantiateSingletons()这方法执行。

实现

beanFactory.preInstantiateSingletons();

// 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();
				}
			}
}

DefaultListableBeanFactory 这个类的实例是怎么构造注入的?构造函数注入。

另外的方法:Bean获取ApplicationContext是需要实现Aware接口的,类似这样:

//spring @EventListner 处理器
public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware {
	private ConfigurableApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		Assert.isTrue(applicationContext instanceof ConfigurableApplicationContext,
				"ApplicationContext does not implement ConfigurableApplicationContext");
		this.applicationContext = (ConfigurableApplicationContext) applicationContext;
	}

© 著作权归作者所有

OrangeJoke
粉丝 39
博文 54
码字总数 36089
作品 0
江北
高级程序员
私信 提问
EventListener原理

目录 目录 流程 initApplicationEventMulticaster() registerListeners() finishRefresh() publishEvent() @EventListener处理 流程 容器的刷新流程如下: 其中与EventListener有关联的步骤 ......

4rnold
2018/08/12
0
0
聊聊spring cloud的AsyncLoadBalancerAutoConfiguration

序 本文主要研究一下AsyncLoadBalancerAutoConfiguration AsyncLoadBalancerAutoConfiguration spring-cloud-commons-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/client/loadba......

go4it
2018/07/17
0
0
聊聊spring cloud的LoadBalancerAutoConfiguration

序 本文主要研究一下spring cloud的LoadBalancerAutoConfiguration RibbonAutoConfiguration spring-cloud-netflix-ribbon-2.0.0.RC2-sources.jar!/org/springframework/cloud/netflix/ribb......

go4it
2018/07/16
0
0
Spring Bean生命周期-finishBeanFactoryInitialization(九)

这个方法应该是ApplicationContext刷新的时候,最重要的方法了,因为所有的bean,如果不是lazy-init的都会在这一步进行实例化,并且做一些处理。 狭义上的Bean生命周期就在这一步进行完成,我...

Real_man
2018/10/12
0
0
深入Spring Boot:Spring Context的继承关系和影响

前言 对于一个简单的Spring boot应用,它的spring context是只会有一个。 非web spring boot应用,context是 web spring boot应用,context是 是spring boot里自己实现的一个context,主要功...

横云断岭
2018/12/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

运维规范

命名规范 发布流程 监控告警 故障定位 状态 日志 监控

以谁为师
34分钟前
1
0
约瑟夫环(报数游戏)java实现

开端 公司组织考试,一拿到考题,就是算法里说的约瑟夫环,仔细想想 以前老师将的都忘了,还是自己琢磨把~ package basic.gzy;import java.util.Iterator;import java.util.LinkedList;...

无极之岚
51分钟前
2
0
Kernel字符设备驱动框架

Linux设备分为三大类:字符设备,块设备和网络设备,这三种设备基于不同的设备框架。相较于块设备和网络设备,字符设备在kernel中是最简单的,也是唯一没有基于设备基础框架(device结构)的...

yepanl
今天
3
0
Jenkins 中文本地化的重大进展

本文首发于:Jenkins 中文社区 我从2017年开始,参与 Jenkins 社区贡献。作为一名新成员,翻译可能是帮助社区项目最简单的方法。 本地化的优化通常是较小的改动,你无需了解项目完整的上下文...

Jenkins中文社区
昨天
4
0
Spring中如何使用设计模式

关于设计模式,如果使用得当,将会使我们的代码更加简洁,并且更具扩展性。本文主要讲解Spring中如何使用策略模式,工厂方法模式以及Builder模式。 1. 策略模式 关于策略模式的使用方式,在S...

爱宝贝丶
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部