【Spring注解】02-生命周期

Spring 注解驱动开发【生命周期】

1. @Bean指定初始化和销毁方法

bean的生命周期

1
2
bean的生命周期:
创建 -> 初始化 -> 销毁

注入spring后 由容器对bean的生命周期进行管理:
我们可以自定义初始化和销毁方法 容器在bean进行到当前生命周期时调用我们自定义的初始化和销毁方法

1.1.init-Method与destroyMethod

在xml配置文件中定义bean时追加 init-method=”” destroy-method=””

或者

通过@Bean(initMethod=””,destroyMethod=””)进行定义

  • 定义一个实体类Car
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Car {
public Car() {
System.out.println("Car constructor...");
}
// 定义初始化方法
public void init(){
System.out.println("Car init...");
}
// 定义销毁方法
public void destroy(){
System.out.println("Car destroy...");
}
}
  • 定义一个配置类
1
2
3
4
5
6
7
@Configuration
public class ConfigOfLifeCycle {
@Bean(initMethod = "init" , destroyMethod = "destroy")
public Car car(){
return new Car();
}
}
  • 通过测试类进行测试
1
2
3
4
5
6
7
8
9
10
11
12
public class MyTest02 {
@Test
public void test(){
// 创建ioc容器 (单例bean会在创建容器的同时就被实例化,同时进行初始化)
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
System.out.println("容器创建完成....");
// 关闭ioc容器会将所有单例bean一同销毁
context.close();
System.out.println("容器销毁结束...");
}
}

运行结果:

1
2
3
4
5
Car constructor...    
Car init...
容器创建完成....
Car destroy...
容器销毁结束...
  • 给注入的Car进行作用域规定
1
2
@Scope("prototype")
@Bean(initMethod = "init" , destroyMethod = "destroy")
  • 再次进行测试
1
2
容器创建完成....
容器销毁结束...

总结:

1
2
3
4
5
6
7
8
bean的生命周期:
创建 -> 初始化 -> 销毁
创建:单例bean会在创建容器的同时就被实例化
多实例bean会在每次获取的时候创建对象
初始化:对象创建完成并赋值好后 调用初始化方法 多实例bean会在调用bean时进行初始化
通常情况下 可以在初始化时为容器配置一些数据源或初始化数据等
销毁:单例bean容器关闭时进行销毁 多实例bean的销毁不会被spring容器接管
通常情况下 可以在销毁时做一些收尾工作 例如关闭一些连接等

1.2.通过让实体类implements InitializingBean,DisposableBean 进行自定义初始化及销毁

  • 自定义一个实体类并实现spring提供的 InitializingBean(初始化) 和 DisposableBean(销毁)接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Component    //要实现ComponentScan进行组件扫描 
public class Cat implements DisposableBean, InitializingBean {
public Cat() {
System.out.println("Cat constructor...");
}

public void afterPropertiesSet() throws Exception {
System.out.println("Cat afterPropertiesSet....");
}

public void destroy() throws Exception {
System.out.println("Cat destory...");
}

}

  • 给配置类添加扫描组件注解

    1
    2
    3
    4
    @ComponentScan(value = "indi.zhihuali.pojo")
    public class ConfigOfLifeCycle {
    ...
    }
  • 测试

1
2
3
4
5
6
7
8
9
10
    @Test
public void test(){
// 创建ioc容器 (单例bean会在创建容器的同时就被实例化)
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
System.out.println("容器创建完成....");
// 关闭ioc容器会将所有单例bean一同销毁
context.close();
System.out.println("容器销毁结束...");
}
}

运行结果:

1
2
3
4
5
6
7
8
Cat constructor...
Cat afterPropertiesSet....
Car constructor...
Car init...
容器创建完成....
Car destroy...
Cat destory...
容器销毁结束...

可见同样可以进行自定义初始化及销毁配置

1.3.通过使用Spring定义的JSR250注解

1
2
@PostConstruct:在bean创建完成并属性赋值完成时 执行初始化方法
@PreDestroy:在容器销毁bean前通知我们完成清理工作
  • 自定义pojo实体类并注册ioc bean

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @Component
    public class Dog {
    public Dog() {
    System.out.println("dog constructor...");
    }

    // 对象创建并赋值后调用
    @PostConstruct
    public void init(){
    System.out.println("dog @PostConstruct....init....");
    }

    // 对象移除之前
    @PreDestroy
    public void destroy(){
    System.out.println("dog @PreDestroy...destroy...");
    }
    }
  • 测试

1
2
3
4
5
6
7
8
9
@Test
public void test(){
// 创建ioc容器 (单例bean会在创建容器的同时就被实例化)
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
System.out.println("容器创建完成....");
// 关闭ioc容器会将所有单例bean一同销毁
context.close();
System.out.println("容器销毁结束...");
}

输出:

1
2
3
4
5
dog constructor....
dog @PostConstruct....init....
容器创建完成....
dog @PreDestroy...destroy...
容器销毁结束...

2. BeanPostProcessor 后置处理器

2.1.BeanPostProcessor接口的使用

1
2
3
BeanPostProcessor【interface】:bean的后置处理器
postProcessBeforeInitialization:初始化前调用
postProcessAfterInitialization: 初始化后调用

自定义一个实现了BeanPostProcessor接口的类并注册bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Component
// 后置处理器:初始化前后进行工作
public class MyBeanPostProcessor implements BeanPostProcessor {
// bean初始化前工作
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization..."+bean+" name:"+beanName);
return bean;
}

// bean初始化后工作
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization..."+bean+" name:"+beanName);
return bean;
}
}

  • 测试
1
2
3
4
5
6
7
8
9
@Test
public void test(){
// 创建ioc容器 (单例bean会在创建容器的同时就被实例化)
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
System.out.println("容器创建完成....");
// 关闭ioc容器会将所有单例bean一同销毁
context.close();
System.out.println("容器销毁结束...");
}

结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!--spring内部组件初始化前后也同样调用了这两个方法-->
postProcessBeforeInitialization...indi.zhihuali.config.ConfigOfLifeCycle$$EnhancerBySpringCGLIB$$4dd9ed7c@1d016c9 name:configOfLifeCycle
postProcessAfterInitialization...indi.zhihuali.config.ConfigOfLifeCycle$$EnhancerBySpringCGLIB$$4dd9ed7c@1d016c9 name:configOfLifeCycle

<!--自定义bean实现该两种方法-->
<!-- Cat创建 -->
Cat constructor...
<!-- Cat初始化前 -->
postProcessBeforeInitialization...indi.zhihuali.pojo.Cat@167e60c name:cat
<!-- 通过1.2中的方法对Cat进行初始化 -->
Cat afterPropertiesSet....
<!-- Cat初始化结束 -->
postProcessAfterInitialization...indi.zhihuali.pojo.Cat@167e60c name:cat
<!-- Dog创建 -->
dog constructor...
<!-- Dog初始化前 -->
postProcessBeforeInitialization...indi.zhihuali.pojo.Dog@ee5251 name:dog
<!-- 通过1.3中的方法对Dog进行初始化 -->
dog @PostConstruct....init....
<!-- Dog初始化结束 -->
postProcessAfterInitialization...indi.zhihuali.pojo.Dog@ee5251 name:dog
Car constructor...
postProcessBeforeInitialization...indi.zhihuali.pojo.Car@23e5ee name:car
Car init...
postProcessAfterInitialization...indi.zhihuali.pojo.Car@23e5ee name:car
容器创建完成....
Car destroy...
dog @PreDestroy...destroy...
Cat destory...
容器销毁结束...

因此添加了BeanPostProcessor后 bean的生命周期可划分为:

1
2
3
4
5
6
7
8
9
10
bean的生命周期:
创建 -> 初始化 -> 销毁
创建:单例bean会在创建容器的同时就被实例化
多实例bean会在每次获取的时候创建对象
BeanPostProcessor.postProcessBeforeInitialization:初始化前调用
初始化:对象创建完成并赋值好后 调用初始化方法 多实例bean会在调用bean时进行初始化
通常情况下 可以在初始化时为容器配置一些数据源或初始化数据等
BeanPostProcessor.postProcessAfterInitialization: 初始化后调用
销毁:单例bean容器关闭时进行销毁 多实例bean的销毁不会被spring容器接管
通常情况下 可以在销毁时做一些收尾工作 例如关闭一些连接等

2.2.BeanPostProcessor接口的原理

对自定义BeanPostProcessor中的postProcessBeforeInitialization和postProcessAfterInitialization进行debug

upload successful

1
2
3
4
5
6
7
8
9
10
11
12
13
14
原理:(debug)
遍历得到容器中所有的BeanPostProcessor 并逐个执行beforeInitialization
一旦方法返回null,跳出for循环
并且不会执行后边的 BeanPostProcessor 的 applyBeanPostProcessorsBeforeInitialization方法

先执行:
populateBean(beanName, mbd, instanceWrapper); 给bean属性赋值
其次:
initBean{
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
invokeInitMethods(beanName, wrappedBean, mbd); 执行初始化
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

2.3.Spring底层对BeanPostProcessor的使用

在以下场景中会用到:

  1. bean赋值 注入其他组件

  2. @Autowired

  3. 生命周期注解功能

  4. @Async 异步功能