这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
1. @PostConstruct和@PreDestroy
@PostConstruct和@PreDestroy它是Java自己的注解,是JSR-250规范里面定义的一个注解
@PostConstruct注解被用来修饰一个非静态的void()方法。被@PostConstruct注解修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。被@PostConstruct注解修饰的方法通常在构造函数之后,init()方法之前执行
在Spring框架中使用到@PostConstruct注解的,该注解的方法在整个bean初始化中的执行顺序如下:
Constructor(构造方法)→@Autowired(依赖注入)→@PostConstruct(注释的方法)
@PreDestroy注解同样是Java提供的,它也是JSR-250规范里面定义的一个注解。
被@PreDestroy注解修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy注解修饰的方法会在destroy()方法之后,Servlet被彻底卸载之前执行。执行顺序如下所示:
destroy()方法→@PreDestroy→destroy()方法 →bean销毁
案例:
import lombok.Data;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* Description:
*
* @author jack
* @date 2021/8/6 22:26
*/
@Data
public class Car {
private String name;
public Car() {
System.out.println("执行了Car()构造方法");
}
@PostConstruct
public void postConstruct() {
System.out.println("执行了Car#postConstruct初始化方法");
}
@PreDestroy
public void preDestroy() {
System.out.println("执行了Car#preDestroy销毁方法");
}
}
import com.example.beans.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Description:
* 配置类
*
* @author jack
* @date 2021/8/6 22:25
*/
@Configuration
public class MainConfig {
@Bean
public Car car() {
return new Car();
}
}
启动类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Description:
*
* @author jack
* @date 2021/8/6 22:31
*/
public class ApplicationTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(MainConfig.class);
app.close();
}
}
运行结果如下:
2.实现InitializingBean 和 DisposableBean 接口
InitializingBean接口,该接口为bean提供了属性初始化后的处理方法,它只包括afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。
DisposableBean接口在bean的生命周期结束前被调用
DisposableBean接口使用注意事项
多实例bean的生命周期不归Spring容器来管理,这里的DisposableBean接口中的方法是由Spring容器来调用的,所以如果一个多实例bean实现了DisposableBean接口是没有啥意义的,因为相应的方法根本不会被调用,当然了,在XML配置文件中指定了destroy方法,也是没有任何意义的。所以,在多实例bean情况下,Spring是不会自动调用bean的销毁方法的。
单例情况下案例:
import lombok.Data;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* Description:
*
* @author jack
* @date 2021/8/6 22:26
*/
@Data
public class Car implements InitializingBean, DisposableBean {
private String name;
public Car() {
System.out.println("执行了Car()构造方法");
}
@PostConstruct
public void postConstruct() {
System.out.println("执行了Car#postConstruct初始化方法");
}
@PreDestroy
public void preDestroy() {
System.out.println("执行了Car#preDestroy销毁方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("执行了Car#afterPropertiesSet初始化方法");
}
@Override
public void destroy() throws Exception {
System.out.println("执行了Car#destroy销毁方法");
}
}
测试代码不变,测试结果如下
初始化执行流程
Constructor(构造方法)→@Autowired(依赖注入)→@PostConstruct(注释的方法)->InitializingBean#afterPropertiesSet(bean属性赋值后初始化方法)
销毁执行流程
@PreDestroy(注释的方法)->DisposableBean#destroy(bean实现的方法)
多例情况下案例:
import com.example.beans.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
* Description:
* 配置类
*
* @author jack
* @date 2021/8/6 22:25
*/
@Configuration
public class MainConfig {
@Scope(scopeName = "prototype")
@Bean
public Car car() {
return new Car();
}
}
import com.example.beans.Car;
import com.example.config.MainConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Description:
*
* @author jack
* @date 2021/8/6 22:31
*/
public class ApplicationTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(MainConfig.class);
Car car = app.getBean(Car.class);
System.out.println(car);
app.close();
}
}
测试结果如下:
可以看到在容器销毁后并没有调用bean的销毁方法
3.使用@Bean注解的属性设置初始化和销毁方法
import lombok.Data;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* Description:
*
* @author jack
* @date 2021/8/6 22:26
*/
@Data
public class Car implements InitializingBean, DisposableBean {
private String name;
public Car() {
System.out.println("执行了Car()构造方法");
}
@PostConstruct
public void postConstruct() {
System.out.println("执行了Car#postConstruct初始化方法");
}
@PreDestroy
public void preDestroy() {
System.out.println("执行了Car#preDestroy销毁方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("执行了Car#afterPropertiesSet初始化方法");
}
@Override
public void destroy() throws Exception {
System.out.println("执行了Car#destroy销毁方法");
}
public void beanInit() {
System.out.println("执行了Car#beanInit初始化方法");
}
public void beanDestroy() {
System.out.println("执行了Car#beanDestroy销毁方法");
}
}
import com.example.beans.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Description:
* 配置类
*
* @author jack
* @date 2021/8/6 22:25
*/
@Configuration
public class MainConfig {
@Bean(initMethod = "beanInit", destroyMethod = "beanDestroy")
public Car car() {
return new Car();
}
}
测试代码不变,测试结果如下
总结
初始化执行流程
Constructor(构造方法)→@Autowired(依赖注入)→@PostConstruct(注释的方法)->InitializingBean#afterPropertiesSet(bean属性赋值后初始化方法) ->initMethod()(bean的初始化方法)
销毁执行流程
@PreDestroy(注释的方法)->DisposableBean#destroy(bean实现的方法)->destoryMethod()(bean的销毁方法)