怎么深入了解Spring的Bean生命周期
本篇文章为大家展示了怎么深入了解Spring的Bean生命周期,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
什么是 Spring Bean 的生命周期
对于普通的 Java 对象,当 new 的时候创建对象,然后该对象就能够使用了。一旦该对象不再被使用,则由 Java 自动进行垃圾回收。
而 Spring 中的对象是 bean,bean 和普通的 Java 对象没啥大的区别,只不过 Spring 不再自己去 new 对象了,而是由 IoC 容器去帮助我们实例化对象并且管理它,我们需要哪个对象,去问 IoC 容器要即可。IoC 其实就是解决对象之间的耦合问题,Spring Bean 的生命周期完全由容器控制。
Bean的生命周期
Spring bean的生命周期阶段是:
bean定义
:就是从xml或注解定位资源加载读取bean的元信息并定义成一个BeanDefinition对象bean注册
:将BeanDefinition对象根据相应的规则放到缓存池map中实例化
:根据BeanDefinition实例化真正的bean,即是调用构造函数依赖注入
:属性赋值调用setter方法,即是依赖注入(DI)初始化
: 初始化是用户能自定义扩展的阶段销毁
: 销毁是用户能自定义扩展的阶段
注:其他都是在这阶段前后的扩展点
Spring角度查看bean的定义与注册
refresh()
public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); // 准备Bean初始化相关的环境信息,其内部提供了一个空实现的initPropertySources()方法用于提供给用户一个更改相关环境信息的机会 this.prepareRefresh(); // 创建BeanFactory实例,并且注册相关的bean信息 ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); // 注册Aware和Processor实例,并且注册了后续处理请求所需的一些Editor信息 this.prepareBeanFactory(beanFactory); try { // 提供的一个空方法,用于供给子类对已经生成的BeanFactory的一些信息进行定制 this.postProcessBeanFactory(beanFactory); StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); // 调用BeanFactoryPostProcessor及其子接口的相关方法,这些接口提供了一个入口,提供给了调用方一个修改已经生成的BeanDefinition的入口 this.invokeBeanFactoryPostProcessors(beanFactory); // 对BeanPostProcessor进行注册 this.registerBeanPostProcessors(beanFactory); beanPostProcess.end(); // 初始化国际化所需的bean信息 this.initMessageSource(); // 初始化事件广播器的bean信息 this.initApplicationEventMulticaster(); // 提供的一个空方法,供给子类用于提供自定义的bean信息,或者修改已有的bean信息 this.onRefresh(); // 注册事件监听器 this.registerListeners(); // 对已经注册的非延迟(配置文件指定)bean的实例化 this.finishBeanFactoryInitialization(beanFactory); // 清除缓存的资源信息,初始化一些声明周期相关的bean,并且发布Context已被初始化的事件 this.finishRefresh(); } catch (BeansException var10) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10); } // 发生异常则销毁已经生成的bean this.destroyBeans(); // 重置refresh字段信息 this.cancelRefresh(var10); throw var10; } finally { // 初始化一些缓存信息 this.resetCommonCaches(); contextRefresh.end(); } }}
SpringBoot角度查看bean定义和注册
自动加载配置类
bean定义和注册
注:springboot只是比spring多了自动配置相关流程,在spring上做了一层逻辑封装。
实例化,依赖注入,初始化
AbstractAutowireCapableBeanFactory为AutowireCapableBeanFactory接口的一个实现类,其中AbstractAutowireCapableBeanFactory实现类的一个方法doCreateBean()
//位置:AbstractAutowireCapableBeanFactory#doCreateBeanprotected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 实例化阶段 instanceWrapper = this.createBeanInstance(beanName, mbd, args); } ... Object exposedObject = bean; try { // 依赖注入,属性赋值阶段 this.populateBean(beanName, mbd, instanceWrapper); // 初始化阶段 exposedObject = this.initializeBean(beanName, exposedObject, mbd); } catch (Throwable var18) { ... } ...}
可以发现,分别调用三种方法:
createBeanInstance() -> 实例化
populateBean() -> 依赖注入
initializeBean() -> 初始化
销毁
销毁阶段是在容器关闭时调用的,在ConfigurableApplicationContext#close()
至于xxxAware,BeanPostProcessor,BeanFactoryPostProcessor等类,只不过是对主流程的一系列扩展点而已。
Bean的生命周期的扩展点
Spring Bean 的生命周期的扩展点很多,这里不可能全部列出来,只说核心的扩展点。这也就是为什么 Spring 的扩展性很好的原因,开了很多的口子,尽可能让某个功能高内聚松耦合,用户需要哪个功能就用哪个,而不是直接来一个大而全的东西。
Bean级别
这些接口的实现类是基于 Bean 的,只要实现了这些接口的Bean才起作用。
BeanNameAware
BeanFactoryAware
ApplicationContextAware
InitializingBean
DisposableBean
还要很多的xxxAware,这些不常用,下面生命周期测试就不加上,如:
BeanClassLoaderAware
EnvironmentAware
EmbeddedValueResolverAware
ResourceLoaderAware
ApplicationEventPublisherAware
MessageSourceAware
ServletContextAware
容器级别
这些接口的实现类是独立于 Bean 的,并且会注册到 Spring 容器中。一般称它们的实现类为后置处理器。
在 Spring 容器创建任何 Bean 的时候,这些后置处理器都会发生作用
BeanPostProcessor
InstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor 是继承了 BeanPostProcessor)
工厂后处理器接口也是容器级的。在应用上下文装配配置文件之后立即调用:
AspectJWeavingEnabler
ConfigurationClassPostProcessor
CustomAutowireConfigurer
常用接口
InstantiationAwareBeanPostProcessor
该类是 BeanPostProcessor 的子接口,常用的有如下三个方法:
postProcessBeforeInstantiation(Class beanClass, String beanName):在bean实例化之前调用
postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean实例化之后、设置属性前调用
postProcessAfterInstantiation(Class beanClass, String beanName):在bean实例化之后调用
BeanNameAware
BeanNameAware接口是为了让自身Bean能够感知到,只有一个方法setBeanName(String name),获取到自身在Spring容器中的id或name属性。
BeanFactoryAware
该接口只有一个方法setBeanFactory(BeanFactory beanFactory),用来获取当前环境中的 BeanFactory,可以对工厂中的所有bean进行扩展。
ApplicationContextAware
该接口只有一个方法setApplicationContext(ApplicationContext applicationContext),用来获取当前环境中的 ApplicationContext,可以对整个容器进行扩展。
注:有时候并不会调用该接口,这要根据你的IOC容器来决定:Spring IOC容器最低要求是实现BeanFactory接口,而不是实现ApplicationContext接口,对于那些没有实现ApplicationContext接口的容器,在生命周期对应的ApplicationContextAware定义的方法也是不会调用的,只要实现了ApplicationContext接口的容器,才会调用。
BeanPostProcessor
postProcessBeforeInitialization(Object bean, String beanName):在初始化之前调用此方法,Spring 的 AOP 就是利用它实现的。
postProcessAfterInitialization(Object bean, String beanName):在初始化之后调用此方法
InitializingBean
该接口只有一个方法afterPropertiesSet(),在属性注入完成后调用。
凡是继承该接口的类,在初始化bean的时候都会执行该方法,可以进行一些属性配置等工作。
InitializingBean 对应生命周期的初始化阶段,在源码的invokeInitMethods(beanName, wrappedBean, mbd)方法中调用。
DisposableBean
该接口的作用是在对象销毁时调用,可以做一些资源销毁操作。
DisposableBean 类似于InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环取所有实现了DisposableBean接口的Bean然后调用其destroy()方法
常用注解
@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
@Bean声明一个bean,配合@Configuration注解使用
initMethod:声明bean初始化时回调一个方法,该方法需要程序员编写
destroyMethod:声明bean销毁时回调一个方法,该方法需要程序员编写
@PostConstruct
bean的一个基于注解的初始化方法
@PreDestroy
bean的一个基于注解的销毁方法
案例分析
声明一个bean
@Configurationpublic class BeanInitAndDestroyConfig { @Description("测试bean的生命周期") @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod") public MyService myServiceBeanName() {//入参数可注入其他依赖 return new MyService(); }}
声明一个名为:myServiceBeanName的bean
initMethod:bean的初始化方法为:initMethod
destroyMethod:bean的销毁方法为:destroyMethod
Animal实现类
这里只是想用来说明 @Qualifier注解能根据bean名称匹配。
我的服务类
即是针对当前bean只调用一次的接口
public class MyService implements Person, BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean { private Animal animal = null; private ApplicationContext applicationContext; @Override public void service() { this.animal.use(); } public MyService() { System.out.println("2. [bean实例化]:"+this.getClass().getSimpleName()+"----------构造方法"); } @Override @Autowired @Qualifier("dog") public void setAnimal(Animal animal) { System.out.println("5. [bean属性赋值]:dog----依赖注入"); this.animal = animal; } @Override public void setBeanName(String s) { System.out.println("6. 调用【BeanNameAware】--setBeanName:"+s); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("7. 调用【BeanFactoryAware】--setBeanFactory"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; System.out.println("8. 调用【ApplicationContextAware】--setApplicationContext"); } @PostConstruct public void myInit() { System.out.println("10. [初始化] 注解@PostConstruct自定义初始化方法[myInit]"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("11. [初始化] 接口InitializingBean方法[afterPropertiesSet]"); } public void initMethod() { System.out.println("12. [初始化] 注解@Bean自定义初始化方法[initMethod]"); } @PreDestroy public void myDestroy() { System.out.println("14. [销毁] 注解@PreDestroy自定义销毁方法[myDestroy]"); } @Override public void destroy() throws Exception { System.out.println("15. [销毁] 接口DisposableBean方法[destroy]"); } public void destroyMethod() { System.out.println("16. [销毁] 注解@Bean自定义销毁方法[destroyMethod]"); }}
这里实现的接口只作用于当前bean(即是上面@bean定义的bean名为myDefineBeanName)生命周期
后置处理器
每个bean生命周期都执行一次
后置处理器是作用于ioc容器中所有bean的生命周期。
@Componentpublic class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) { System.out.println("============================InstantiationAwareBeanPostProcessor-开始======================"); System.out.println("1. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName为"+beanName); } return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) { System.out.println("3. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName为"+beanName); } return true; } @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) { System.out.println("4. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName为"+beanName); System.out.println("============================InstantiationAwareBeanPostProcessor-结束======================"); } return null; }}
@Componentpublic class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { //这里过滤掉springboot自动配置的bean,只打印我们项目的bean情况 if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) { System.out.println("9. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName为" + beanName); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) { System.out.println("13. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName为" + beanName); } return bean; }}
工厂后置处理器
容器级别,只允许一次
@Componentpublic class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("0. [容器级别只调用一次] 调用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法"); }}
输出结果和结果解读
“//”标记为解读
//容器级别的工厂后置处理器,只在应用上下文装配配置文件之后立即调用1次0. [容器级别只调用一次] 调用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法//因为我们生命过程只打印("myServiceBeanName".equals(beanName) || "dog".equals(beanName)),所有猫只有构造方法打印了猫----------构造方法//###############################dog的生命周期###############################################//后置处理器,容器级别,作用于所有bean============================InstantiationAwareBeanPostProcessor-开始======================1. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName为dog//狗的实例化狗----------构造方法//后置处理器,容器级别,作用于所有bean3. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName为dog//后置处理器,容器级别,作用于所有bean4. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName为dog============================InstantiationAwareBeanPostProcessor-结束======================//后置处理器,容器级别,作用于所有bean9. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName为dog//后置处理器,容器级别,作用于所有bean13. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName为dog//###############################dog的bean完成,开始myServiceBeanName###############################################//后置处理器,容器级别,作用于所有bean============================InstantiationAwareBeanPostProcessor-开始======================1. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName为myServiceBeanName//实例化2. [bean实例化]:MyService----------构造方法//后置处理器,容器级别,作用于所有bean3. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName为myServiceBeanName//后置处理器,容器级别,作用于所有bean4. [容器级别每个bean都回调] 调用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName为myServiceBeanName============================InstantiationAwareBeanPostProcessor-结束======================//属性赋值,即是依赖注入5. [bean属性赋值]:dog----依赖注入//bean级别,bean:myServiceBeanName实现了接口BeanNameAware6. 调用【BeanNameAware】--setBeanName:myServiceBeanName//bean级别7. 调用【BeanFactoryAware】--setBeanFactory//bean级别8. 调用【ApplicationContextAware】--setApplicationContext//后置处理器,容器级别,作用于所有bean:初始化前处理9. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName为myServiceBeanName//初始化10. [初始化] 注解@PostConstruct自定义初始化方法[myInit]11. [初始化] 接口InitializingBean方法[afterPropertiesSet]12. [初始化] 注解@Bean自定义初始化方法[initMethod]//后置处理器,容器级别,作用于所有bean:初始化后处理13. [容器级别每个bean都回调] 调用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName为myServiceBeanName//容器环境加载完成,这时可以使用所有bean2021-12-21 11:18:42.994 INFO 18956 --- [ main] c.l.s.SpringbootBeanLifecycleApplication : Started SpringbootBeanLifecycleApplication in 0.719 seconds (JVM running for 1.312)//销毁14. [销毁] 注解@PreDestroy自定义销毁方法[myDestroy]15. [销毁] 接口DisposableBean方法[destroy]16. [销毁] 注解@Bean自定义销毁方法[destroyMethod]Process finished with exit code 0
Bean生命周期图
了解 Spring 生命周期的意义就在于,可以利用 Bean 在其存活期间的指定时刻完成一些相关操作。一般情况下,会在 Bean 被初始化后和被销毁前执行一些相关操作。
上述内容就是怎么深入了解Spring的Bean生命周期,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网行业资讯频道。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341