前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring - SmartInitializingSingleton扩展接口

Spring - SmartInitializingSingleton扩展接口

作者头像
小小工匠
发布2022-12-09 14:13:43
6680
发布2022-12-09 14:13:43
举报
文章被收录于专栏:小工匠聊架构

文章目录

在这里插入图片描述
在这里插入图片描述

Pre

Spring Boot - 扩展接口一览

在这里插入图片描述
在这里插入图片描述

org.springframework.beans.factory.SmartInitializingSingleton

代码语言:javascript
复制
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之后。


使用场景

可以扩展此接口在对所有单例对象初始化完毕后,做一些后置的业务处理

在这里插入图片描述
在这里插入图片描述

源码解析

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
org.springframework.context.support.AbstractApplicationContext#refresh
	org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
		org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
			smartSingleton.afterSingletonsInstantiated();

在Spring容器启动时,会调用方法refresh();

代码语言:javascript
复制
@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

代码语言:javascript
复制
@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			 // .... 

			try {
			 		
				 // ....

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				 // ....
			}

			catch (BeansException ex) {
			 // ....
			}

			finally {
			 // ....
			}
		}
	}

继续

代码语言:javascript
复制
	/**
	 * 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();
	}

继续

代码语言:javascript
复制
	@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();
				 
			}
		}
	}

扩展示例

代码语言:javascript
复制
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");

    }
}
在这里插入图片描述
在这里插入图片描述

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • Pre
  • org.springframework.beans.factory.SmartInitializingSingleton
  • 触发时机
  • 使用场景
  • 源码解析
  • 扩展示例
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档