首页IT科技spring的生命周期简单回答(Spring Bean的生命周期)

spring的生命周期简单回答(Spring Bean的生命周期)

时间2025-05-04 21:42:19分类IT科技浏览5971
导读:说明: 本文基于Spring-Framework 5.1.x版本讲解...

说明: 本文基于Spring-Framework 5.1.x版本讲解

概述

说起生命周期, 很多开源框架             、中间件的组件都有这个词             ,其实就是指组件从创建到销毁的过程             。 那这里讲Spring Bean的生命周期,并不是讲Bean是如何创建的, 而是想讲下Bean从实例化到销毁                    ,Spring框架在Bean的各个阶段给我们提供了哪些拓展点                    。 Bean本身有三个大的阶段: 实例化                    、初始化       、销毁       。

Spring的强大就是提供了非常多的拓展点, 我们可以基于这些拓展点实现不同的需求      。 回到主题       ,Spring容器围绕着生命周期的各个阶段提供了不同功能的拓展点如下图:

从上图可以看到      ,整个生命周期涉及到的接口(当然这不是所有接口,只是日常中可以用到的                    ,还有一部分是Spring内部的接口)分成了4个阶段:

1. 实例化阶段: 主要是以不同方式实例化Bean

2. 属性注入阶段:IOC的过程

3. 初始化阶段:初始化Bean的内部组件             、生成代理对象等都在这里

4. 销毁阶段: 释放资源

下面我们对这些核心的接口进行简单的介绍

接口介绍

InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

@Nullable default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { return null; }

返回值Object:返回null值则执行Spring提供给我们的Bean实例化                    、属性注入       、初始化阶段, 这是对于大多数Bean的选择;返回非null值则跳过Bean实例化      、属性注入                    、初始化阶段              ,因为Spring会认为IOC等阶段由使用者管理      ,所以在这种情况下后续会直接调用BeanPostProcessor#postProcessAfterInitialization接口, 进而有可能提前结束标准IOC流程                   , 为什么说有可能呢? 因为还需取决于BeanPostProcessor#postProcessAfterInitialization的返回值                    。

使用场景: 使用频率比较低              ,实际没有用到过              。不过在Spring-Framework的AOP源码中有用到,见AbstractAutoProxyCreator

InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { return true; }

返回值boolean: true则执行Spring的属性注入功能 , 大多数情况返回true即可                   ,除非你有定制化的需求;返回false跳过Spring属性注入功能                    ,意味着@Resource             、@Autowired等注解失效,也意味着xml文件中<property>标签失效      。

使用场景: 比较少, Spring-Framework源码中也没有用到

InstantiationAwareBeanPostProcessor#postProcessProperties

@Nullable default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { return null; }

返回值PropertyValues: 一般返回入参pvs即可, Spring后续会使用返回值进行属性注入                   。 尤其对于SpringBoot这种纯JavaConfig配置的方式, 参数pvs一般为Empty(注意与null区分)

使用场景:标注@Resource      、@Autowired等注解的属性都在这个方法实现注入             ,比较核心, 详见: CommonAnnotationBeanPostProcessor                    、AutowiredAnnotationBeanPostProcessor

如果postProcessProperties方法返回null                    ,Spring也会调用postProcessPropertyValues方法实现同样的效果       ,不过这个方法是老版本中的             ,已经弃用掉的                    ,不推荐使用.

@Deprecated @Nullable default PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { return pvs; }

BeanName             、BeanFactory、BeanClassLoaderAware

public interface BeanNameAware extends Aware { void setBeanName(String name); } public interface BeanClassLoaderAware extends Aware { void setBeanClassLoader(ClassLoader classLoader); } public interface BeanFactoryAware extends Aware { void setBeanFactory(BeanFactory beanFactory) throws BeansException; }

这三个接口就比较简单了       ,就是给我们的Bean注入BeanName                    、ClassLoader                    、BeanFactory属性      , 他的调用时机在实例化、属性注入之后                    ,是初始化阶段的第一步

BeanPostProcessor#postProcessBeforeInitialization

/** * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean * initialization callbacks (like InitializingBeans {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>The default implementation returns the given {@code bean} as-is. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet */ @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; }

返回值Object: 一般情况返回入参的bean即可              。

需要注意几点:

1. 如果返回null              ,则后续所有实现该接口的Processor都不会执行      ,且返回上个Processor的返回值;

2. 上个Processor的返回值会作为下个Processor的入参。

3. 最后一个Processor的返回值会代替原来的Bean(返回入参Bean的情况可以忽略这一条)进行后续处理(包含Bean初始化             、以及最终暴露到Spring容器中)

这里比较难理解                   ,贴下源码

/** * 执行Bean的初始化步骤 */ protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { // 此处省略不关键的部分代码 Object wrappedBean = bean; // 调用所有实现BeanPostProcessor#postProcessBeforeInitialization接口的方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); // 使用postProcessBeforeInitialization方法的返回值当做入参进行Bean初始化 invokeInitMethods(beanName, wrappedBean, mbd); // 使用postProcessBeforeInitialization方法的返回值当做入参进行Bean初始化的后置处理 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); return wrappedBean; } @Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; // getBeanPostProcessors() 返回的Processors是有有优先级顺序的 for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; // 如果为null , 这里直接退出该方法并返回上次Processor返回的结果 } result = current; // 上个Processor执行的结果作为下个Processor处理的入参 } return result; }

使用场景:1. 标注@PostConstruct注解的方法都在该接口实现调用, 详见InitDestroyAnnotationBeanPostProcessor 2. 各种Aware接口的调用入口              ,详见ApplicationContextAwareProcessor

InitializingBean#afterPropertiesSet

public interface InitializingBean { /** * Invoked by the containing {@code BeanFactory} after it has set all bean properties * and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc. * <p>This method allows the bean instance to perform validation of its overall * configuration and final initialization when all bean properties have been set. * @throws Exception in the event of misconfiguration (such as failure to set an * essential property) or if initialization fails for any other reason */ void afterPropertiesSet() throws Exception; }

Bean初始化资源的回调接口 , 与@PostConstruct一样的作用                    ,但要注意的是几个初始化方法调用的顺序:1.@PostConstruct2. afterPropertiesSet 3. init-method

使用场景: 资源初始化                    、可以使用回调的特性实现策略模式等                    ,实际工作中用的较多

init-method

XML配置文件中init-method属性或者@Bean注解initMethod属性指定的方法 , 比较简单不多说了

BeanPostProcessor#postProcessAfterInitialization

/** * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean * initialization callbacks (like InitializingBeans {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. * The returned bean instance may be a wrapper around the original. * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean * instance and the objects created by the FactoryBean (as of Spring 2.0). The * post-processor can decide whether to apply to either the FactoryBean or created * objects or both through corresponding {@code bean instanceof FactoryBean} checks. * <p>This callback will also be invoked after a short-circuiting triggered by a * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * in contrast to all other BeanPostProcessor callbacks. * <p>The default implementation returns the given {@code bean} as-is. * @param bean the new bean instance * @param beanName the name of the bean * @return the bean instance to use, either the original or a wrapped one; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */ @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; }

返回值Object: 一般情况返回入参的bean即可                   。

与postProcessBeforeInitialization方法的调用逻辑一样             ,需要注意几点:

1. 如果返回null                    ,则后续所有实现该接口的Processor都不会执行       ,且返回上个Processor的返回值;

2. 上个Processor的返回值会作为下个Processor的入参                    。

3. 最后一个Processor的返回值会代替原来的Bean(返回入参Bean的情况可以忽略这一条)进行后续处理(包含Bean初始化       、以及最终暴露到Spring容器中)

使用场景:AOP生成代理的入口,详见AbstractAutoProxyCreator

DestructionAwareBeanPostProcessor#postProcessBeforeDestruction

/** * Apply this BeanPostProcessor to the given bean instance before its * destruction, e.g. invoking custom destruction callbacks. * <p>Like DisposableBeans {@code destroy} and a custom destroy method, this * callback will only apply to beans which the container fully manages the * lifecycle for. This is usually the case for singletons and scoped beans. * @param bean the bean instance to be destroyed * @param beanName the name of the bean * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.DisposableBean#destroy() * @see org.springframework.beans.factory.support.AbstractBeanDefinition#setDestroyMethodName(String) */ void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

用于处理Bean销毁前的一些前置工作             ,可实现批量处理。

使用场景:标注@PreDestroy注解的方法都在该接口实现调用, 详见InitDestroyAnnotationBeanPostProcessor

DisposableBean#destroy

/** * Invoked by the containing {@code BeanFactory} on destruction of a bean. * @throws Exception in case of shutdown errors. Exceptions will get logged * but not rethrown to allow other beans to release their resources as well. */ void destroy() throws Exception;

Bean直接实现该接口即可                    ,同时也注意这几个销毁方法的调用顺序: 1.@PreDestroy2. destroy 3. destroy-method

使用场景:释放Bean本身持有的资源       ,如连接池Bean资源等       ,单个处理             。

destroy-method

XML配置文件中destroy-method属性或者@Bean注解destroyMethod属性指定的方法                     , 比较简单不多说了

小结

围绕生命周期Spring容器给我们提供的接口就简单介绍到这              ,实际上除了上面列举的接口之外      ,还有一些不常用的接口我没有列举出来                   ,如:SmartInstantiationAwareBeanPostProcessor             、MergedBeanDefinitionPostProcessor等                    。对于以上接口              ,个人理解没有必要像八股文一样死记硬背每个接口的作用,甚至尝试记住接口的名称                   ,关键在于设计的思想                    ,开头也说过,其他框架的组件也有生命周期的实现             ,Spring与这些框架实现上有什么不同                    ,这才是应该了解的;当然完全不了解其接口的作用也是不行的       ,这里强调的是不用刻意去死记硬背接口的含义             , 在工作中多看看别人                    、别的框架的使用方式更有利于加深理解       。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
解决跨域的三种方法(解决跨域Access to XMLHttpRequest at ‘http://localhost:8080/xxx’ from origin ‘http://localhost:63342) 日本服务器地址与端口有关吗为什么(日本服务器ping不通如何解决)