Spring学习 之Bean生命周期

mac2024-05-31  31

文章目录

理解Bean的生命周期接口分类流程简述案例代码BeanDefinition阶段Bean实例化阶段Bean初始化阶段Bean销毁阶段

理解Bean的生命周期

在Bean准备就绪给我们使用之前,容器默默的执行了很多启动步骤。Spring提供了BeanFactory作为Spring容器,平常开发中我们常用其派生类ApplicationContext。 尽管BeanFactory和ApplicationContext容器的注册方式不大一样(使用BeanFactory要显示的调用其addBeanPostProcessor()方法进行注册)以及加载bean的时机不一样(BeanFactory默认采用延迟加载)等,但对于Bean的生命周期管控基本一致。 这里就以ApplicationContext来说。 Bean的完整生命周期可以认为是从容器创建初始化Bean开始,直到Spring容器关闭。 事实上,在Bean被初始化创建之前,容器级别的接口方法也会对Bean产生影响,因此这里把这两个事件也加进来了。

接口分类

在以上接口方法中, 可以分为几类:

1、容器级生命周期接口方法【灰色底色】: BeanFactoryPostProcessor、BeanPostProcessor和InstantiationAwareBeanPostProcessor。它们都是容器初始化bean时对外暴露的扩展点(容器扩展点),一般称它们的实现类为“后置处理器”。InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,可以在Bean生命周期的另外三个时期提供扩展的回调接口,即实例化Bean之前(调用postProcessBeforeInstantiation方法)、给bean注入对应属性后(调用postProcessPropertyValues方法)和实例化Bean之后(调用postProcessAfterInstantiation方法)。2、Bean级生命周期接口方法【浅蓝色底色】: BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean。bean继承接口然后在bean内部实现方法,因此属于Bean级生命周期接口方法。3、Bean自身的调用方法【浅红色底色】: 通过配置文件中的init-method和destroy-method指定的方法。

流程简述

1、[容器级]BeanFactoryPostProcessor接口: 如果spring配置文件注册了该接口的实现类,可以在spring的bean创建之前,修改bean的定义属性。例如可以把bean的scope从singleton改为prototype。 2、[容器级]InstantiationAwareBeanPostProcessor接口: 初始化Bean之前的预处理; 3、初始化Bean 4、[容器级]InstantiationAwareBeanPostProcessor接口: 如果spring配置文件注册了该接口的实现类,Spring将调用它们的postProcessPropertyValues方法; 5、注入: Spring根据定义信息(beanDifinition)将值和引用bean注入到bean对应的属性中; 6、[Bean级]感知类名: 如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBeanName()方法; 7、[Bean级]感知容器: 如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传入进来。注:BeanFactory容器查找实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入. 8、[容器级]BeanPostProcessor: 如果bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessBeforeInitialization()方法; 9、[Bean级]InitializingBean: 如果bean实现了InitializingBean接口,Spring将调用它们的after-PropertiesSet()方法。 10、[Bean自身方法]init-method: 如果bean定义中使用指定了init-method初始化方法,该方法也会被调用; 11、[容器级]BeanPostProcessor: 如果bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessAfterInitialization()方法; 12、[容器级/后处理器]InstantiationAwareBeanPostProcessor : 如果bean实现了InstantiationAwareBeanPostProcessor 接口,Spring将调用它们的postProcessAfterInitialization()方法;

此时,bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;

13、[Bean级]DisposableBean: 如果bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法。 14、[Bean自身方法]destroy-method: 如果bean定义中使用destroy-method声明了销毁方法,该方法也会被调用。

可以自己写一个类,然后实现各个bean级接口,在每个实现方法中输出一句。然后实现容器级接口,再到配置文件中注册,最后运行程序查看各个接口方法执行顺序。

案例代码

InstantiationAwareBeanPostProcessor接口实现:

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { /** * BeanPostProcessor 接口中的方法 * 在Bean的自定义初始化方法之前执行 * Bean对象已经存在了 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("拦截到Bean的初始化之前:" + beanName); return bean; } /** * BeanPostProcessor接口中的方法 * 在Bean的自定义初始化方法执行完成之后执行 * Bean对象已经存在了 */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("拦截到Bean的初始化之后:" + beanName); return bean; } /** * InstantiationAwareBeanPostProcessor中自定义的方法 * 在方法实例化之前执行 Bean对象还没有 */ @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { System.out.println("拦截到Bean的实例化之前:" + beanName); return null; } /** * InstantiationAwareBeanPostProcessor中自定义的方法 * 在方法实例化之后执行 Bean对象已经创建出来了 */ @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { System.out.println("拦截到Bean的实例化之后:" + beanName); return true; } }

BeanPostProcessor 接口实现:

@Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("拦截到Bean的初始化之前:" + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("拦截到Bean的初始化之后:" + beanName); return bean; } }

业务类:

@Component public class Person implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean { private ApplicationContext applicationContext; public Person() { System.out.println("执行Bean构造函数进行实例化:person"); } @Override public void setBeanName(String beanName) { System.out.println("setBeanName:" + beanName); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("setApplicationContext"); this.applicationContext = applicationContext; } @PostConstruct public void postConstruct() { System.out.println("@PostConstruct注解方法"); } @PreDestroy public void preDestroy() { System.out.println("@PreDestroy注解方法"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("实现InitializingBean接口的方法afterPropertiesSet"); } @Override public void destroy() throws Exception { System.out.println("实现DisposableBean接口的方法destroy"); } }

测试:

public class App { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext("org.example"); applicationContext.close(); } }

运行结果:

BeanDefinition阶段

首先,bean 的生命周期分为 BeanDefinition 阶段和 bean 实例化阶段。(能在 bean 的生命周期中回答出 BeanDefinition 非常重要,是加分项!) BeanDefinition 阶段分为加载 xml 配置文件、解析注解配置类、编程式构造 封装出 BeanDefinition ,最后注册到 BeanDefinitionRegistry 。

Bean实例化阶段

InstantiationAwareBeanPostProcessor接口实现的实例化方法之前 Bean的构造函数 InstantiationAwareBeanPostProcessor接口实现的实例化方法之后

Bean初始化阶段

Bean 对象实例化完成后,进入到初始化阶段,会进行属性赋值、组件依赖注入,以及初始化阶段的方法回调。 在属性赋值、依赖注入阶段,会事先收集好 Bean 中标注了依赖注入的注解( @Autowired 、@Value 、@Resource 、@Inject ),之后会借助后置处理器的初始化之前方法实现属性赋值、依赖注入。

属性赋值和依赖注入之后,会回调执行 Bean 的初始化方法,以及后置处理器的逻辑:首先会执行 Aware 相关的回调注入,之后执行后置处理器的前置回调,在后置处理器的前置方法中,会回调 bean 中标注了 @PostConstruct 注解的方法,所有的后置处理器前置回调后,会执行 InitializingBean 的 afterPropertiesSet 方法,随后是 init-method 指定的方法,等这些 bean 的初始化方法都回调完毕后,最后执行后置处理器的后置回调。

Bean销毁阶段

Bean 对象在销毁时,由 ApplicationContext 发起关闭动作。 由 BeanFactory 取出所有单实例 bean ,并逐个销毁。

先将当前 Bean 依赖的所有 Bean 都销毁。 随后回调自定义的 Bean 的销毁方法。 之后如果 bean 中有定义内部 bean 则会一并销毁。 最后销毁那些依赖了当前 bean 的 bean 也一起销毁。

最新回复(0)