您现在的位置是:首页 > 文章详情

Spring SmartInitializingSingleton

日期:2019-05-15点击:357

使用场景

我们在这样的场景下使用,当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; } 
原文链接:https://my.oschina.net/tigerlene/blog/3049797
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章