文章目录
简述
Bean的生命周期分为
创建 contruct
初始化 initialize
运行 runtime
销毁 destroy
Spring主要针对初始化和销毁两个时期做文章
加载Bean(单例)的代码基本流程是:
- 读取配置文件(XML或者@Configuration标注的类)
- 解析配置文件中的类,并且对每个要加载的bean执行:
2.1 通过反射调用构造方法创建类
2.2 对bean进行赋值
2.3 对bean调用多个XXXPostProcessor进行后置处理
通过@Bean注解
可以通过@Bean注解设置Bean的加载和销毁方法
- 编写Soil类作为Bean并同时设置加载的init方法以及销毁的destroy方法
public class Soil {
public void init() {
System.out.println("soil inited");
}
public void destroy() {
System.out.println("soil destroy");
}
}
- 编写配置类MainConfig6
在@Bean注解中指定initMethod 和destroyMethod
@Configuration
public class MainConfig6 {
@Bean(initMethod = "init", destroyMethod = "destroy")
public Soil soil() {
return new Soil();
}
}
- 编写MainTest6测试并输出
public class MainTest6 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig6.class);
context.removeBeanDefinition("soil");
}
}
输出:
soil inited
soil destroy
注意事项
- 注意@Bean注解的destroyMethod 方法中有个注释(init方法也有):
表明了哪些方法可以作为destroyMethod 方法,以及别的注意事项
/**
* The optional name of a method to call on the bean instance upon closing the
* application context, for example a {@code close()} method on a JDBC
* {@code DataSource} implementation, or a Hibernate {@code SessionFactory} object.
* The method must have no arguments but may throw any exception.
*As a convenience to the user, the container will attempt to infer a destroy
* method against an object returned from the {@code @Bean} method. For example, given
* an {@code @Bean} method returning an Apache Commons DBCP {@code BasicDataSource},
* the container will notice the {@code close()} method available on that object and
* automatically register it as the {@code destroyMethod}. This ‘destroy method
* inference’ is currently limited to detecting only public, no-arg methods named
* ‘close’ or ‘shutdown’. The method may be declared at any level of the inheritance
* hierarchy and will be detected regardless of the return type of the {@code @Bean}
* method (i.e., detection occurs reflectively against the bean instance itself at
* creation time).
*To disable destroy method inference for a particular {@code @Bean}, specify an
* empty string as the value, e.g. {@code @Bean(destroyMethod=“”)}. Note that the
* {@link org.springframework.beans.factory.DisposableBean} and the
* {@link java.io.Closeable}/{@link java.lang.AutoCloseable} interfaces will
* nevertheless get detected and the corresponding destroy/close method invoked.
*Note: Only invoked on beans whose lifecycle is under the full control of the
* factory, which is always the case for singletons but not guaranteed for any
* other scope.
* @see org.springframework.context.ConfigurableApplicationContext#close()
- 注意如果bean的scope设置多例(prototype),将不会调用Init和destroy方法
@Configuration
public class MainConfig6 {
@Bean(initMethod = "init", destroyMethod = "destroy")
@Scope(value = "prototype")
public Soil soil() {
return new Soil();
}
}
输出:
空
小结
所以Bean的生命周期:
Spring的IOC容器只会接管单例bean,而不会接管多例Bean的生命周期。
通过InitializingBean, DisposableBean接口
- 编写Docker类并实现InitializingBean, DisposableBean两个接口
public class Docker implements InitializingBean, DisposableBean {
public void afterPropertiesSet() throws Exception {
System.out.println("docker inited");
}
public void destroy() throws Exception {
System.out.println("docker destroy");
}
}
- 配置类MainConfig6中将Docker类的实例加入IOC容器
@Configuration
public class MainConfig6 {
@Bean
public Docker docker() {
return new Docker();
}
}
- 运行MainTest6并测试
public class MainTest6 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig6.class);
context.removeBeanDefinition("docker");
}
}
Docker类的创建和销毁的钩子函数成功被调用
docker inited
docker destroy
通过@PostConstruct和@PreDestroy注解
这两个不是Spring的注解哦
- 编写Dog类
public class Dog {
@PostConstruct
public void init() {
System.out.println("Dog inited");
}
@PreDestroy
public void destroy() {
System.out.println("Dog destroy");
}
}
- 设置配置类
@Configuration
public class MainConfig6 {
@Bean
public Dog dog() {
return new Dog();
}
}
- 运行测试类查看输出
public class MainTest6 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig6.class);
context.removeBeanDefinition("dog");
}
}
Dog inited
Dog destroy
通过BeanPostProcessor接口
这个接口在bean初始化前(postProcessBeforeInitialization)和初始化后(postProcessAfterInitialization)调用的,并且对所有bean生效。
Spring中大量使用了BeanPostProcessor,比如AOP通过它对初始化完的bean进行增强实现了代理
- 编写类BeanPostProcessor的子类MyBeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String s) throws BeansException {
System.out.println("postProcessBeforeInitialization ->" + bean);
return bean;
}
public Object postProcessAfterInitialization(Object bean, String s) throws BeansException {
System.out.println("postProcessAfterInitialization ->" + bean);
return bean;
}
}
- 编写配置类MainConfig6
@Configuration
public class MainConfig6 {
@Bean
public MyBeanPostProcessor myBeanPostProcessor() {
return new MyBeanPostProcessor();
}
@Bean
public Dog dog() {
return new Dog();
}
@Bean
public Docker docker() {
return new Docker();
}
@Bean(initMethod = "init", destroyMethod = "destroy")
public Soil soil() {
return new Soil();
}
}
3.运行测试类MainTest6并查看输出结果
postProcessBeforeInitialization ->org.springframework.context.event.EventListenerMethodProcessor@782663d3
postProcessAfterInitialization ->org.springframework.context.event.EventListenerMethodProcessor@782663d3
postProcessBeforeInitialization ->org.springframework.context.event.DefaultEventListenerFactory@64485a47
postProcessAfterInitialization ->org.springframework.context.event.DefaultEventListenerFactory@64485a47
postProcessBeforeInitialization ->my.spring.test6.Dog@4524411f
Dog inited
postProcessAfterInitialization ->my.spring.test6.Dog@4524411f
postProcessBeforeInitialization ->my.spring.test6.Docker@1786f9d5
docker inited
postProcessAfterInitialization ->my.spring.test6.Docker@1786f9d5
postProcessBeforeInitialization ->my.spring.test6.Soil@704d6e83
soil inited
postProcessAfterInitialization ->my.spring.test6.Soil@704d6e83
观察到dog类的输出(5 - 7 行)
postProcessBeforeInitialization ->my.spring.test6.Dog@4524411f
Dog inited
postProcessAfterInitialization ->my.spring.test6.Dog@4524411f
Dog类
public class Dog {
// 初始化
@PostConstruct
public void init() {
System.out.println("Dog inited");
}
@PreDestroy
public void destroy() {
System.out.println("Dog destroy");
}
}
可知:BeanPostProcessor的处理时机是在bean的初始化前后;
初始化前调用postProcessBeforeInitialization方法;初始化之后调用
postProcessAfterInitialization方法。