Spring 注解驱动开发_生命周期

bean 的生命周期意思是指从 Bean 创建,到 Bean 初始化,再到销毁的过程
Spring IoC 容器管理 bean 的生命周期,我们可以自定义初始化和销毁方法,容器在 bean 进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。

一、@Bean 指定初始化和销毁方法

1.1 创建实体类 Car,在实体类中创建初始化方法以及销毁方法

package org.example.pojo;

public class Car {

    public Car(){
        System.out.println("car constructor...");
    }

    public void initCar(){
        System.out.println("car ... initCar...");
    }

    public void destroyCar(){
        System.out.println("car ... destroyCar");
    }
}

1.2 创建配置类,同时向容器中注入实体类 Car

在通过 @Bean 注解向容器中注入 Car 时,同时添加初始化和销毁方法。添加方法:在 @Bean 注解中新增 initMethod 和 destoryMethod
两个属性,用以指定需要添加的初始化和销毁方法。

package org.example.config;

import org.example.pojo.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class InitAndDestoryTestConfig {
    @Scope
    @Bean(initMethod = "initCar", destroyMethod = "destroyCar")
    public Car car(){
        return new Car();
    }
}

1.3 测试方法

@Test
public void testInitAndDestroy(){
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(InitAndDestroyTestConfig.class);
    System.out.println("容器创建完成......");
    Object car = ac.getBean("car");
    Object car1 = ac.getBean("car");
    System.out.println(car);
    System.out.println(car1);
    System.out.println(car == car1);
    ac.close();
}

测试结果:
在这里插入图片描述

再来测一下当 Scope 为 多实例时的情况:
将配置类中 @Scope 的 value 属性修改为 ”prototype“,测试方法不变,进行测试,测试结果如下:
在这里插入图片描述

1.4 总结

单实例多实例
构造函数(对象创建)时间在容器启动的时候创建对象在每次获取的时候创建对象
初始化时间对象创建完成,并赋值好,调用初始化方法对象创建完成,并赋值好,调用初始化方法
销毁时间在容器关闭的时候调用销毁方法容器不会管理bean,故而容器不会调用销毁方法

二、InitializingBean 和 DisposableBean

2.1 接口定义

2.1.1 InitializingBean 接口定义

public interface InitializingBean {
	void afterPropertiesSet() throws Exception;
}

在容器对 bean 进行初始化时,如果该 bean 实现了InitializingBean 接口,将会调用接口中的 afterPropertiesSet() 方法,完成一些用户自定义的初始化操作。

2.1.2 DisposableBean 接口

public interface DisposableBean {
	void destroy() throws Exception;
}

BeanFactory 将在单实例 bean 销毁时调用 destroy 方法。

2.1.3 案例

实体类 Car 实现InitializingBean 和 DisposableBean 接口

package org.example.pojo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class Car implements InitializingBean, DisposableBean {

    public Car(){
        System.out.println("car constructor...");
    }

    public void initCar(){
        System.out.println("car ... initCar...");
    }

    public void destroyCar(){
        System.out.println("car ... destroyCar");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("car......DisposableBean......destroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("car......InitializingBean......afterPropertiesSet");
    }
}

配置类以及测试方法保持不变,测试结果如下:
在这里插入图片描述

2.1.4 总结

当一个实体类中既通过 @Bean 注解指定了 initMethod 以及 destroyMethod,还实现了 InitializingBean 和 DisposableBean 接口,那么容器在初始化时会优先执行 InitializingBean 中的 afterPropertiesSet() 方法,而在销毁阶段,DisposableBean 中的 destroy 方法的执行顺序也是优先于 @Bean 注解指定的销毁方法的。

三、使用 JSR250

3.1 @PostConstruct 注解

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}

标有 @PostConstruct 注解的方法,容器在 bean 创建完成并且属性赋值完成后,会调用该初始化方法。

3.2 @PreDestroy 注解

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}

标有 @PreDestroy 注解的方法,会在容器销毁 bean 之前进行调用

3.3 案例

修改实体类 Car:

package org.example.pojo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class Car implements InitializingBean, DisposableBean {

    public Car(){
        System.out.println("car constructor...");
    }

    public void initCar(){
        System.out.println("car ... initCar...");
    }

    public void destoryCar(){
        System.out.println("car ... destoryCar");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("car......DisposableBean......destory");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("car......InitializingBean......afterPropertiesSet");
    }

    @PostConstruct
    public void initPostConstruct(){
        System.out.println("car......initPostConstruct......");
    }

    @PreDestroy
    public void initPreDestroy(){
        System.out.println("car......initPreDestroy......");
    }
}

配置类以及测试方法不变,测试结果:
在这里插入图片描述
可以看出带有 @PostConstruct 注解和@PreDestroy 注解的方法其执行顺序要优先于其他两种方式。

四、使用 BeanPostProcessor 接口

4.1 接口介绍

BeanPostProcessor 是一个接口,它是 bean 的后置处理器,该接口会在 bean 初始化前后进行一些处理工作。

接口源码:

public interface BeanPostProcessor {

	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

  • postProcessBeforeInitialization 方法:在初始化之前工作
  • postProcessAfterInitialization:在初始化之后工作
  • 方法参数 bean:bean 实例
  • 方法参数 beanName:bean 实例的名称
  • 返回值:返回值为原始的 bean 实例或者经过包装后的 bean 实例,如果返回值为 null,后续的 BeanPostProcessor 将不会被执行。

4.2 案例

创建 MyBeanPostProcessor 类,实现 BeanPostProcessor 接口,同时将 MyBeanPostProcessor 类通过 @Component 注解注入到容器中。

package org.example.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..." + beanName + "--->" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization..." + beanName + "--->" + bean);
        return bean;
    }
}

配置类 InitAndDestoryTestConfig 添加注解 @ComponentScan(“org.example.processor”),将 MyBeanPostProcessor 同过包扫描的方式注入到容器中。

package org.example.config;

import org.example.pojo.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("org.example.processor")
public class InitAndDestoryTestConfig {
    @Bean(initMethod = "initCar", destroyMethod = "destoryCar")
    public Car car(){
        return new Car();
    }
}

测试方法不变,测试结果如下:
在这里插入图片描述

4.3 总结

BeanPostProcessor 中的 postProcessBeforeInitialization 方法执行时间要先于其他三种方式,但是 postProcessAfterInitialization 方法与其他三种销毁方法是不一样的,该方法是在 bean 初始化完成之后执行,并不属于销毁方法。

五、总结

本节内容总共介绍了四种初始化方法,以及三种销毁方法,另外 BeanPostProcessor 中的 postProcessAfterInitialization 并不属于销毁方法,该方法是在 bean 初始化完成之后执行的。
四种初始化方法的执行时间优先顺序如下:
BeanPostProcessor 中的 postProcessBeforeInitialization > @PostConstruct 注解 > InitializingBean 接口中的 afterPropertiesSet 方法 > @Bean 注解中 initMethod 属性指定的初始化方法

三种销毁方法的执行时间优先顺序如下:
@PreDestroy 注解 > DisposableBean 接口中的 destroy 方法 > @Bean 注解中 destroyMethod 属性指定的初始化方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值