The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications - on any kind of deployment platform.

声明周期@Bean指定初始化和销毁方法

Bean的生命周期

Bean的创建、初始化和销毁是由容器帮我们管理的

我们可以自定义初始化和销毁方法,容器在进行到当前生命周期的时候来调用我买自定义的初始化和销毁方法

构造(对象创建)

​ 单实例: 在容器启动的时候创建

​ 多实例: 在每次获取的时候创建对象

指定初始化方法

初始化:对象创建完成后,并赋值化,调用初始化方法

销毁:单实例是在容器关闭的时候销毁,多实例容器不会管理这个Bean,容器不会调用销毁方法

编写一个Car类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*** @Author: cuzz* @Date: 2018/9/23 21:20* @Description:*/
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...");}
}

在xml中我们可以指定init-methoddestroy-method方法,如

1
<bean id="car" class="com.cuzz.bean.Car" init-method="init" destroy-method="destroy"></bean>

使用注解我们可以

1
2
3
4
5
6
7
8
9
10
11
12
13
/*** @Author: cuzz* @Date: 2018/9/24 12:49* @Description: 配置类*/
@Configuration
public class MainConfigOfLifecycle {@Bean(initMethod = "init", destroyMethod = "destroy")public Car car() {return new Car();}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*** @Author: cuzz* @Date: 2018/9/24 13:00* @Description:*/
public class IOCTestLifeCycle {@Testpublic void test01() {// 创建ioc容器AnnotationConfigApplicationContext applicationContext =new AnnotationConfigApplicationContext(MainConfigOfLifecycle.class);System.out.println("容器创建完成...");// 关闭容器System.out.println("--->开始关闭容器");applicationContext.close();System.out.println("--->已经关闭容器");}
}

可以看出先创建car,再调用init方法,在容器关闭时销毁实例

1
2
3
4
5
6
car constructor...
car...init...
容器创建完成...
--->开始关闭容器
car...destroy...
--->已经关闭容器

在配置数据源的时候,有很多属性赋值,销毁的时候要把连接给断开

生命周期InitializingBean和DisposableBean

InitializingBean

可以通过Bean实现InitializingBean来定义初始化逻辑,是设置好所有属性会调用afterPropertiesSet()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface InitializingBean {/*** Invoked by a BeanFactory after it has set all bean properties supplied* (and satisfied BeanFactoryAware and ApplicationContextAware).* <p>This method allows the bean instance to perform initialization only* possible when all bean properties have been set and to throw an* exception in the event of misconfiguration.* @throws Exception in the event of misconfiguration (such* as failure to set an essential property) or if initialization fails.*/void afterPropertiesSet() throws Exception;}

DisposableBean

可以通过Bean实现DisposableBean来定义销毁逻辑,会调用destroy()方法

1
2
3
4
5
6
7
8
9
10
11
public interface DisposableBean {/*** Invoked by a BeanFactory on destruction of a singleton.* @throws Exception in case of shutdown errors.* Exceptions will get logged but not rethrown to allow* other beans to release their resources too.*/void destroy() throws Exception;}

例子

编写一个Cat类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*** @Author: cuzz* @Date: 2018/9/24 13:36* @Description:*/
public class Cat implements InitializingBean, DisposableBean{public Cat() {System.out.println("cat constructor...");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("cat...init...");}@Overridepublic void destroy() throws Exception {System.out.println("cat...destroy...");}}

测试

1
2
3
4
5
6
cat constructor...
cat...init...
容器创建完成...
--->开始关闭容器
cat...destroy...
--->已经关闭容器

生命周期@PostContruct和@PreDestroy注解

@PostContruct在Bean创建完成并且属性赋值完成,来执行初始化

@PreDestroy在容器销毁Bean之前通知我们进行清理工作

编写一个Dog类,并把他注入到配置类中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*** @Author: cuzz* @Date: 2018/9/24 14:03* @Description:*/
public class Dog {public Dog() {System.out.println("dog constructor...");}@PostConstructpublic void postConstruct() {System.out.println("post construct...");}@PreDestroypublic void preDestroy() {System.out.println("pre destroy...");}
}

测试结果

1
2
3
4
5
6
dog constructor...
post construct...
容器创建完成...
--->开始关闭容器
pre destroy...
--->已经关闭容器

生命周期BeanPostProscessor后置处理器

我们先看看源码,解释的很清楚,BeanPostProscessor 中postProcessBeforeInitialization方法会在每一个bean对象的初始化方法调用之前回调;postProcessAfterInitialization方法会在每个bean对象的初始化方法调用之后被回调 。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*** Factory hook that allows for custom modification of new bean instances,* e.g. checking for marker interfaces or wrapping them with proxies.** <p>ApplicationContexts can autodetect BeanPostProcessor beans in their* bean definitions and apply them to any beans subsequently created.* Plain bean factories allow for programmatic registration of post-processors,* applying to all beans created through this factory.** <p>Typically, post-processors that populate beans via marker interfaces* or the like will implement {@link #postProcessBeforeInitialization},* while post-processors that wrap beans with proxies will normally* implement {@link #postProcessAfterInitialization}.*/
public interface BeanPostProcessor {/*** Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}* or a custom init-method). The bean will already be populated with property values.* The returned bean instance may be a wrapper around the original.* @param bean the new bean instance* @param beanName the name of the bean* @return the bean instance to use, either the original or a wrapped one;* if {@code null}, no subsequent BeanPostProcessors will be invoked* @throws org.springframework.beans.BeansException in case of errors* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet*/Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;/*** Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}* or a custom init-method). The bean will already be populated with property values.* The returned bean instance may be a wrapper around the original.* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean* instance and the objects created by the FactoryBean (as of Spring 2.0). The* post-processor can decide whether to apply to either the FactoryBean or created* objects or both through corresponding {@code bean instanceof FactoryBean} checks.* <p>This callback will also be invoked after a short-circuiting triggered by a* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,* in contrast to all other BeanPostProcessor callbacks.* @param bean the new bean instance* @param beanName the name of the bean* @return the bean instance to use, either the original or a wrapped one;* if {@code null}, no subsequent BeanPostProcessors will be invoked* @throws org.springframework.beans.BeansException in case of errors* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet* @see org.springframework.beans.factory.FactoryBean*/Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;}

编写一个MyBeanPostProcessor实现BeanPostProcessor接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*** @Author: cuzz* @Date: 2018/9/24 14:21* @Description: 后置处理器,初始化前后进行处理工作*/
public class MyBeanPostProcessor implements BeanPostProcessor{@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("--->postProcessBeforeInitialization..." + beanName +"==>" + bean);return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("--->postProcessAfterInitialization..." + beanName +"==>" + bean);return bean;}
}

添加到配置中

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
public class MainConfigOfLifecycle {@Beanpublic Cat cat() {return new Cat();}@Beanpublic MyBeanPostProcessor myBeanPostProcessor() {return new MyBeanPostProcessor();}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
--->postProcessBeforeInitialization...org.springframework.context.event.internalEventListenerProcessor==>org.springframework.context.event.EventListenerMethodProcessor@1dc67c2
--->postProcessAfterInitialization...org.springframework.context.event.internalEventListenerProcessor==>org.springframework.context.event.EventListenerMethodProcessor@1dc67c2
--->postProcessBeforeInitialization...org.springframework.context.event.internalEventListenerFactory==>org.springframework.context.event.DefaultEventListenerFactory@2bd765
--->postProcessAfterInitialization...org.springframework.context.event.internalEventListenerFactory==>org.springframework.context.event.DefaultEventListenerFactory@2bd765
cat constructor...
--->postProcessBeforeInitialization...cat==>com.cuzz.bean.Cat@1d3b207
cat...init...
--->postProcessAfterInitialization...cat==>com.cuzz.bean.Cat@1d3b207
容器创建完成...
--->开始关闭容器
cat...destroy...
--->已经关闭容器

在实例创建之前后创建之后会被执行

生命周期BeanPostProcessor原理

通过debug到populateBean,先给属性赋值在执行initializeBean方法

1
2
3
4
5
6
try {populateBean(beanName, mbd, instanceWrapper);if (exposedObject != null) {exposedObject = initializeBean(beanName, exposedObject, mbd);}
}

initializeBean方法时,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {// 执行before方法wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}...try {// 执行初始化invokeInitMethods(beanName, wrappedBean, mbd);}if (mbd == null || !mbd.isSynthetic()) {// 执行after方法wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}

Spring底层对BeanPostProcessor的使用

Bean赋值、注入其他组件、@Autowired、生命周期注解功能、@Async等等都使用到了BeanPostProcessor这个接口的实现类,很重要

总结

Bean 的初始化顺序

  1. 首先执行 bean 的构造方法
  2. BeanPostProcessor 的 postProcessBeforeInitialization 方法
  3. InitializingBean 的 afterPropertiesSet 方法
  4. @Bean 注解的 initMethod方法
  5. BeanPostProcesso r的 postProcessAfterInitialization 方法
  6. DisposableBean 的 destroy 方法
  7. @Bean注解的 destroyMethod 方法

Spring注解驱动开发(二)相关推荐

  1. 【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解

    写在前面 最近,二狗子入职了新公司,新入职的那几天确实有点飘.不过慢慢的,他发现他身边的人各个身怀绝技啊,有Spring源码的贡献者,有Dubbo源码的贡献者,有MyBatis源码的贡献者,还有研究A ...

  2. Spring注解驱动开发学习总结8:自动装配注解@Autowire、@Resource、@Inject

    Spring注解驱动开发学习总结8:自动装配注解@Autowire.@Resource.@Inject 1.自动装配@Autowire.@Resource.@Inject 1.1 构建bookDao ...

  3. spring注解驱动开发-10 Servlet3.0

    Spring AOP实现 前言 servlet3.0简介 ServletContainerInitializer shared libraries(共享库) / runtimes pluggabili ...

  4. 0、Spring 注解驱动开发

    0.Spring注解驱动开发 0.1 简介 <Spring注解驱动开发>是一套帮助我们深入了解Spring原理机制的教程: 现今SpringBoot.SpringCloud技术非常火热,作 ...

  5. Spring注解驱动开发第26讲——总有人让我给他讲讲@EnableAspectJAutoProxy注解

    @EnableAspectJAutoProxy注解 在配置类上添加@EnableAspectJAutoProxy注解,便能够开启注解版的AOP功能.也就是说,如果要使注解版的AOP功能起作用的话,那么 ...

  6. SPRING注解驱动开发-雷神课程超详细笔记

    SPRING注解驱动开发-雷神课程超详细笔记 时间:2021-03-21 2022-04-06更新:最近翻起一年多前写的笔记复习,还是收获颇多,很多当时无法理解的知识现在慢慢能理解了,可能是工作一年的 ...

  7. spring注解驱动开发-5 Spring AOP实现

    Spring AOP实现 前言 AOP案例实现 1.编写目标类 2.编写切面类 3.编写配置类 4.编写测试类 end... 前言 AOP为Aspect Oriented Programming的缩写 ...

  8. spring注解驱动开发-8 Spring 扩展原理

    Spring 扩展原理 前言 BeanFactoryPostProcessor 测试实例编写 ExtConfig MyBeanFactoryPostProcessor ExtTest 源码分析 Bea ...

  9. spring注解驱动开发-4 Spring 自动装配

    Spring 自动装配 前言 Spring 自动装配的几种方式 1.@Autowired @Qualifier("组件id") @Primary 2.@Resource方式 3.@ ...

  10. spring注解驱动开发-7 Spring声明式事务

    Spring 声明式事务 前言 @EnableTransactionManagement AutoProxyRegistrar InfrastructureAdvisorAutoProxyCreato ...

最新文章

  1. 【Java多线程编程】选号程序
  2. ab753变频器参数怎么拷贝到面板_技术贴:100吨连铸安川变频器的更换
  3. junit的使用说明
  4. centos7服务器文件同步,centos7文件实时同步工具lsyncd
  5. Kafka的10道基础面试题
  6. 关于软件系统维护的一点想法
  7. 集结号!四大国产开源数据库共聚申城,共话未来技术演进
  8. 图形界限命令在命令行输入_CAD骚操作,恭喜你又学会了几个重要的命令
  9. 如何设置几个循环出来的span其中一个宽度_css几个概念
  10. Git简洁教程:本地项目如何与GitHub互连
  11. K8s部署Nexus3管理Docker镜像
  12. Python编程之二维码生成
  13. Ribbon界面制作
  14. 用EXCEL分析房价
  15. 如何查找并修改CAD图纸中的标注文字?
  16. 如何帮银行保持长期竞争力?融360天机公布独家秘诀
  17. 用python批量导入阿里云安全组规则
  18. Hbase Schema设计与数据模型操作
  19. oracle asm密码是什么,ASM有自己的参数、密码、alert、监听文件
  20. [梁山好汉说IT] 用实例来深入理解容器概念

热门文章

  1. Matlab根据相噪计算抖动
  2. Linux C/C++ or 嵌入式面试之《网络编程系列》(7) time_wait状态的若干问题
  3. 发现一只野生无知的小宾
  4. SICK OD2位移测量传感器单双张检测调试实例
  5. vscode快捷设置左侧导航栏和文本字体大小
  6. arcgis api for js4.x 移动端--按钮点击实现地图旋转
  7. windows c++ 串口通讯
  8. (二)Alian 的 Spring Cloud Parent(父工程)
  9. Alian解读SpringBoot 2.6.0 源码(四):启动流程分析之应用环境准备
  10. 凯撒密码加密算法python_Python密码学入门:凯撒密码