【spring注解】3.spring生命周期相关注解

文章目录

  • 1. 什么是bean的生命周期
  • 2. 四种方式定义bean的初始化及销毁方法
    • 2.1 @Bean指定初始化及销毁方法
      • 使用场景
      • 单实例bean初始化及销毁方法的调用时机
      • 多实例bean初始化及销毁方法的调用时机
    • 2.2 让Bean实现InitializingBean及DisposableBean接口
    • 2.3 @PostConstruct和@PreDestroy注解定义初始化及销毁方法
    • 2.4 BeanPostProcessor后置处理器

  前面几篇文章主要记录了spring组件注册涉及到的spring相关的注解。我们已经可以成功在spring容器中注册bean实例,本篇文章主要来学习一下bean生命周期相关的注解。

1. 什么是bean的生命周期

bean的生命周期指的是从bean创建到初始化到销毁的全过程。

bean创建
初始化
销毁

而在spring容器管理的bean的生命周期也是由spring容器管理。即spring容器帮我们创建bean,初始化以及销毁。前面几篇文章关于spring组件的注册即为多种创建bean的方法,对于初始化和销毁,我们也可以自定义方法,当bean进行到对应的生命周期的时候,spring会帮我们调用我们自定义的初始化或销毁方法。

2. 四种方式定义bean的初始化及销毁方法

2.1 @Bean指定初始化及销毁方法

对于之前xml配置bean的方式来讲,可以通过指定init-method及destroy-method属性来定义bean的初始化及销毁方法

<bean id="student" class="com.xinhua.study.bean.Student" scope="prototype" init-method="init()" destroy-method="destroy()"/>

接下来演示注解方式如何配置bean的初始化及销毁方法。直接在@Bean注解上定义initMethod及destroyMethod的属性值即可。

  1. 在com.xinhua.study.bean下创建Teacher类,并创建方法init及destroy
@Slf4j
public class Teacher {

    public Teacher(){
        log.info("Teacher类的构造器...");
    }

    public void init(){
        log.info("Teacher类的初始化方法...");
    }

    public void destroy(){
        log.info("Teacher类的销毁方法...");
    }
}

  1. 在com.xinhua.study.config下创建AnnotationConfigOfLifeCycle配置类
@Configuration
public class AnnotationConfigOfLifeCycle {

	//在此定义bean的初始化及销毁方法
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Teacher teacher() {
        return new Teacher();
    }
}

3.测试,在src/test/java的com
.xinhua.study.test下创建AnnotationConfigTestOfLifeCycle测试类

@Slf4j
public class AnnotationConfigTestOfLifeCycle {

    @Test
    public void testInitAndDestroyMethod(){

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationConfigOfLifeCycle.class);

    }
}

测试方法中,仅仅创建了一下spring容器。先来查看下测试结果:
【spring注解】3.spring生命周期相关注解_第1张图片
之前的文章我们提到过,单实例bean在容器创建完成时就已经创建成功,我们可以看到Teacher类的构造器已经被调用,同时初始化方法也已经被调用。也就是在容器创建完成时,单实例的bean已经完成了创建及初始化的操作,那么我们的销毁方法何时调用呢?修改一下测试类中的testInitAndDestroyMethod方法,并调用spring容器的close方法。注意,要想调用spring容器的close方法,就不能将容器类型直接声明为ApplicationContext。

	@Test
    public void testInitAndDestroyMethod(){
        //测试容器的关闭时不能将容器声明为ApplicationContext,因为这个接口本身不包含close方法,只能声明为其实现类
//        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationConfigOfLifeCycle.class);
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationConfigOfLifeCycle.class);

        log.info("容器创建完成");
        applicationContext.close();
    }

看一下测试结果:
销毁方法测试
bean实例的销毁方法是在spring容器关闭时才会调用。

使用场景

比如数据源的创建。初始化时要赋值驱动、url等很多属性,在销毁时我们需要关闭数据源连接。就可以在自定义的初始化及销毁方法中做这些操作。

单实例bean初始化及销毁方法的调用时机

初始化方法在bean创建及赋值完成后调用
销毁方法在spring容器关闭时调用

多实例bean初始化及销毁方法的调用时机

初始化方法获取bean实例时候才会调用
多实例bean的销毁方法不会被spring管理调用,需要自己在适当时候手动调用。

2.2 让Bean实现InitializingBean及DisposableBean接口

  1. 在com.xinhua.study.bean下创建Teacher2类,并实现InitializingBean, DisposableBean接口
@Slf4j
public class Teacher2 implements InitializingBean, DisposableBean {

    public Teacher2(){
        log.info("Teacher2 constructor...");
    }

    @Override
    public void destroy() throws Exception {
        log.info("Teacher2 destroy...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("Teacher2 init...");
    }
}

  1. 在AnnotationConfigOfLifeCycle配置类中添加
	@Bean
    public Teacher2 teacher2() {
        return new Teacher2();
    }
  1. 调用AnnotationConfigTestOfLifeCycle测试类的testInitAndDestroyMethod方法,测试结果:
    【spring注解】3.spring生命周期相关注解_第2张图片
    由此,可以看出通过实现两个接口,也成功为Teacher2类定义了初始化及销毁方法。

2.3 @PostConstruct和@PreDestroy注解定义初始化及销毁方法

  1. 修改之前创建的Teacher类,在init方法上添加@PostContrust注解,在destroy方法上添加@PreDestroy注解
@Slf4j
public class Teacher {

    public Teacher(){
        log.info("Teacher类的构造器...");
    }

    @PostConstruct()
    public void init(){
        log.info("Teacher类的初始化方法...");
    }

    @PreDestroy
    public void destroy(){
        log.info("Teacher类的销毁方法...");
    }
}

  1. 修改AnnotationConfigOfLifeCycle配置类中teacher方法上的@Bean注解,去掉initMethod及destroyMethod属性
	@Bean
    public Teacher teacher() {
        return new Teacher();
    }
  • 调用AnnotationConfigTestOfLifeCycle测试类的testInitAndDestroyMethod方法,测试结果:
    【spring注解】3.spring生命周期相关注解_第3张图片
    可以看出此种方式也可以正常定义Bean的初始化及销毁方法。

2.4 BeanPostProcessor后置处理器

BeanPostProcessor是Spring提供的一个组件,点开看下源码:
BeanPostProcessor源码结构
BeanPostProcessor是一个接口,提供了postProcessBeforeInitialization
以及postProcessAfterInitialization两个方法,主要用于在Bean初始化前后做一些处理工作。
查看注释发现:

  • postProcessBeforeInitialization:在bean初始化之前被调用(在initMethod或者afterPropertiesSet方法之前调用)
  • postProcessAfterInitialization:在bean初始化之后被调用(initMethod或者afterPropertiesSet方法之后调用)

1.在com.xinhua.study.bean下创建MyBeanPostProcessor类

@Slf4j
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.info("{}初始化之前执行",beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("{}初始化之后执行",beanName);
        return bean;
    }
}

  1. 在AnnotationConfigOfLifeCycle配置类上添加@ComponentScan(“com.xinhua.study.bean”)包扫描注解,用于将我们新建的MyBeanPostProcessor注册到容器中
  2. 调用AnnotationConfigTestOfLifeCycle测试类的testInitAndDestroyMethod方法,测试结果:
    【spring注解】3.spring生命周期相关注解_第4张图片
    可以看出,在bean初始化前后添加了相应的输出操作,bean后置处理器已经生效。

到现在为止,bean的创建到初始化到初始化前后的拦截以及到销毁整个生命周期,我们都可以自己去实现啦~

你可能感兴趣的:(spring注解,spring,java,spring,boot)