Spring Bean 生命周期回调

Stella981
• 阅读 685

#Spring生命周期回调说明

如果只是简单的对象初始化,我们可以将其放到构造器中处理;如果是对注入的类或者帮助类做一些初始化处理,可以考虑使用初始化方法。
Spring提供了很多的扩展点,其中就有生命周期回调,我们可以在bean初始化之前做一些处理,在bean销毁之前做一些处理。

#早期Spring生命周期扩展方式

InitializingBean: 允许在bean实例化并且设置好所有的必要属性之后,执行初始化一些处理。 DisposableBean: bean销毁前获得一次回调,做一些处理。

#initMethod和destroyMethod

当初我们使用标签来配置bean的时候,我们可以通过init-method和destroy-method来指定bean自定义的回调方法。 当使用@Bean注解来配置bean的时候,我们通过@Bean(initMethod="customInit")@Bean(destroyMethod="customDestroy")来指定bean的自定义回调方法。

#推荐扩展方式

@PostStruct: InitializingBean的替代方案 @PreDestroy:DisposableBean的替代方案

#几种回调方式的顺序 可以看到Spring提供的回调方式有很多种,但是在处理这些回调的时候顺序是怎样的呢,在不看源码之前,我们可以通过实验来看一下执行顺序。

public class BeanOrder implements InitializingBean, DisposableBean{
    
    public void customInit(){
        System.out.println("***我是通过配置init-method来实现的初始化方法。");
    }
    
    public void customDestroy(){
        System.out.println("***我是通过配置destroy-method来实现的初始化方法。");
    }
    
    @PostConstruct
    public void initMethod(){
        System.out.println("***我是加了@PostConstruct注解的init方法。");
    }
    
    @PreDestroy
    public void destroyMethod(){
        System.out.println("***我是加了@PreDestroy注解的destroy方法。");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("***我是实现DisposableBean接口的destroy方法。");
        
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("***我是实现InitializingBean接口的afterPropertiesSet方法。");
    }
}

#####执行结果如下:

***我是加了@PostConstruct注解的init方法。
***我是实现InitializingBean接口的afterPropertiesSet方法。
***我是通过配置init-method来实现的初始化方法。
 
***我是加了@PreDestroy注解的destroy方法。
***我是实现DisposableBean接口的destroy方法。
***我是通过配置destroy-method来实现的初始化方法。

#代码演练 ####InitializingBean

/**
 * 
 * Spring官方已经不推荐这种方式来扩展Bean的初始化操作。
 * @author Xiaoyang.Li
 *
 * https://github.com/superliyang
 */
@Component
public class UseInitializingBean implements InitializingBean{
    public void afterPropertiesSet() throws Exception {
        System.out.println("实现InitializingBean接口来完成初始化操作,跟@PostConstruct意义一样。");
    }
}  

####DisposableBean

@Component
public class UseDisposableBean implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("实现DisposableBean接口来实现bean销毁之前做一些操作。");
    }
}

当然了,一般很少单独使用DisposableBean,很多时候我们只是单独使用InitializingBean,或者同时使用InitializingBean和DisposableBean 。

####@PostConstruct and PreDestroy

/**
 * 生命周期回调(Bean lifecycle callback)
 * Bean的生命周期扩展是很重要的,首先要知道,bean在生命周期有哪些地方可以自定义扩展。
 * Bean通过@PostConstruct和@PreDestroy来扩展生命周期内的操作。
 * 关于使用构造器和初始化方法的分析:如果只是简单的对象初始化,我们可以将其放到构造器中处理;如果是对注入的类或者帮助类做一些初始化处理,可以考虑使用初始化方法。
 * @author Xiaoyang.Li (https://github.com/superliyang)
 *
 */
@Component
public class BeanLifeCycleExample {
    
    public BeanLifeCycleExample(){
        System.out.println("初始化构造器");
    }
    
    @PostConstruct
    public void initMethod(){
        //该方式跟在xml中bean标签上设置init-method是一样的。
        //<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
        System.out.println("@PostConstruct允许容器bean创建并设置好所有必要属性之后,做出一些初始化处理");
    }
    
    @PreDestroy
    public void destroyMethod(){
        //该方式跟在xml中bean标签上设置destroy-method是一样的。
        //<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
        System.out.println("@PreDestroy允许在bean销毁之前做出一些处理");
    }
    
    public void postProcessBeforeInitializationTest(){
        System.out.println("在bean实例化完成,调用初始化方法之前,来调用我吧。");
    }
    
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java常用类(2)
三、时间处理相关类Date类:计算机世界把1970年1月1号定为基准时间,每个度量单位是毫秒(1秒的千分之一),用long类型的变量表示时间。Date分配Date对象并初始化对象,以表示自从标准基准时间(称为“历元”(epoch),即1970年1月1日08:00:00GMT)以来的指定毫秒数。示例:packagecn.tanjian
Easter79 Easter79
3年前
Spring中管理Bean依赖注入之后和Bean销毁之前的行为
    对于Singleton作用域的Bean,Spring容器将会跟踪它们的生命周期,容器知道何时实例化结束、何时销毁。Spring可以管理Bean在实例化结束之后和Bean销毁之前的行为。Bean依赖关系注入之后的行为:    Spring提供了两种方式在Bean全部属性设置成功后执行特定的行为:在Spring配置文件
Stella981 Stella981
3年前
Spring 回顾 (Spring 扩展之 BeanPostProcessor 接口)
BeanPostProcessor的作用BeanPostProcessor主要用来在bean初始化之后做相应的处理,例如参数的注入等等。BeanPostProcessor接口说明BeanPostProcessor接口存在两个方法,一个在初始化之前被调用,一个在初始化之后被调用。(这里的初始化是指调用了Spring的初始化方法,例如加注
Easter79 Easter79
3年前
Spring的BeanFactoryPostProcessor接口
接口简介BeanFactoryPostProcessor接口是Spring初始化BeanFactory时对外暴露的扩展点,SpringIoC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义,并可以修改它。BeanDefinitionRegistryPostPro
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
SpringAOP源码跟踪及学习
Spring版本4.3.2在拿到Bean实例以后,会经历一系列的初始化工作,如:工厂回调、init方法、后处理器在Bean初始化前后的处理等,在一般情况下(非factorymethod创建的Bean等),AOP代理对象的创建就在后处理器的处理方法中实现。入口以AbstractAutowireCapableB
Easter79 Easter79
3年前
Spring高级应用之注入嵌套Bean
在Spring中,如果某个Bean所依赖的Bean不想被Spring容器直接访问,可以使用嵌套Bean。和普通的Bean一样,使用<bean元素来定义嵌套的Bean,嵌套Bean只对它的外部的Bean有效,Spring容器无法直接访问嵌套的Bean,因此定义嵌套Bean也无需指定id属性。如下配置片段是一个嵌套Bean的示例:<bean id