赞
踩
目录
1、定义bean信息文件applicationContext.xml
3、创建InstantiationAwareBeanPostProcessor 接口实现类
5、创建BeanFactoryPostProcessor 接口实现类
网上谈这个问题的很多,但基本都是按照源码的执行顺序,时间久了很容易忘记。
换个思路,spring作为一个非常优秀的框架,从设计者的角度去考虑,bean的生命周期是怎么被设计出来的?或者说是怎么被完善的?反而更容易理解!
有时候看了很多博文,可能也被以下问题弄的一头雾水:
我们从先找突破点。
任何一门技术,最权威的解释还是对应的官方,所以第一步应该是从官网入手。
打开官网,我们先找下官方对Spring容器以及bean的相关介绍:
图中标注部分,简而言之就是以下两个意思:
1、org.springframework.beans和org.springframework.context是非常关键的两个包;
2、ApplicationContext 继承了BeanFactory(可以感觉到,这两个对象应该比较关键);
既然官网这么说,我们就从BeanFactory 和 ApplicationContext 入手:
先看下BeanFactory源码中的注释,尤其是第一句:
- /**
- * The root interface for accessing a Spring bean container.
- *
- * ...省略...
- *
- *
- * <p>Bean factory implementations should support the standard bean lifecycle interfaces
- * as far as possible. The full set of initialization methods and their standard order is:
- * <ol>
- * <li>BeanNameAware's {@code setBeanName}
- * <li>BeanClassLoaderAware's {@code setBeanClassLoader}
- * <li>BeanFactoryAware's {@code setBeanFactory}
- * <li>EnvironmentAware's {@code setEnvironment}
- * <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
- * <li>ResourceLoaderAware's {@code setResourceLoader}
- * (only applicable when running in an application context)
- * <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
- * (only applicable when running in an application context)
- * <li>MessageSourceAware's {@code setMessageSource}
- * (only applicable when running in an application context)
- * <li>ApplicationContextAware's {@code setApplicationContext}
- * (only applicable when running in an application context)
- * <li>ServletContextAware's {@code setServletContext}
- * (only applicable when running in a web application context)
- * <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
- * <li>InitializingBean's {@code afterPropertiesSet}
- * <li>a custom init-method definition
- * <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
- * </ol>
- *
- * <p>On shutdown of a bean factory, the following lifecycle methods apply:
- * <ol>
- * <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
- * <li>DisposableBean's {@code destroy}
- * <li>a custom destroy-method definition
- * </ol>
- *
- * ...省略...
- *
- */
- public interface BeanFactory {...}
注释中第一句:
源码注释:
The root interface for accessing a Spring bean container.
字面翻译:
访问SpringBean容器的根接口
为什么SpringBean被称为根接口,它做了什么?
继续看BeanFactory源码:
源码注释:
Bean factory implementations should support the standard bean lifecycle interfaces
* as far as possible. The full set of initialization methods and their standard order is:... ...
翻译过来还是两点:
1、定义了一个标准的bean的生命周期。
2、规范了bean在整个生命周期中,各个方法的执行顺序。
从这里看出,BeanFactory应该是起点,那么ApplicationContext又有什么不同?
官方给出了明确的回复,简单理解:
BeanFactory是发展大纲,定义了发展方向;
ApplicationContext 是执行守则,定义了执行方向。
通过分析ApplicationContext的继承关系,确实也继承了BeanFactory,所以分析bean的生命周期自然通过BeanFactory入手。
通常我们会在这里先提供一个完整的流程图来展示整个流程,这种思维方式是按照阅读源码的方式,逻辑清晰,但是时间长了容易忘记。
按照官网文档的描述,我们可以换个方式,从bean的自身方法、生命周期、容器管理三个层级来思考,然后逐层补充扩展来看下。
这是官方提供的对bean的定义,可以归为四类:构造方法、属性、初始化(init-method)、bean销毁(destory-method)。
结合源码,我们可以梳理出bean自身的生命周期:
The Spring Framework provides a number of interfaces you can use to customize the nature of a bean. This section groups them as follows:
- Lifecycle Callbacks
- ApplicationContextAware and BeanNameAware
- Other Aware Interfaces
在官网可以到,spring对bean提供了很多扩展接口,这些接口也贯穿bean的生命周期,这些接口也会和spring容器进行交互,保持bean自身及在spring容器整个过程中生命周期的一致性。
Aware接口在开篇BeanFactory源码注释中已经说明了调用顺序,所以,bean的生命周期流程图又拓展为:
继续跟官方文档:
Lifecycle Callbacks
To interact with the container’s management of the bean lifecycle, you can implement the Spring InitializingBean and DisposableBean interfaces. The container calls afterPropertiesSet() for the former and destroy() for the latter to let the bean perform certain actions upon initialization and destruction of your beans.
新增了bean初始化方法和容器销毁的方法
为避免引起歧义,原来的“初始化”节点,加上了“init-method”标注。
到这里,bean自身以及拓展的阶段以及完成,bean开始由spring容器进行管理。
容器主要通过BeanPostProcessor进行管理bean,BeanPostProcessor被称为后置处理器:
- public interface BeanPostProcessor {
- Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
- Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
- }
postProcessBeforeInitialization方法会在每一个bean对象的初始化方法调用之前回调;
postProcessAfterInitialization方法会在每个bean对象的初始化方法调用之后被回调。
于是,流程图继续完善:
原本到这里,按照BeanFactory中的方法调用,可以结束了,但是在阅读 BeanPostProcessor源码时,提到了InstantiationAwareBeanPostProcessor
/**
* @author Juergen Hoeller
* @author Sam Brannen
* @since 10.10.2003
* @see InstantiationAwareBeanPostProcessor
* @see DestructionAwareBeanPostProcessor
* @see ConfigurableBeanFactory#addBeanPostProcessor
* @see BeanFactoryPostProcessor
*/
public interface BeanPostProcessor {...}
InstantiationAwareBeanPostProcessor是BeanFactory的子类,用法和BeanFactory类似.
- /**
- * Subinterface of {@link BeanPostProcessor} that adds a before-instantiation callback,
- * and a callback after instantiation but before explicit properties are set or
- * autowiring occurs.
- * ...
- */
- public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
-
- //在bean实例化之前调用
- postProcessBeforeInstantiation(Class beanClass, String beanName){...}
- //在bean实例化之后、设置属性前调用
- postProcessProperties(PropertyValues pvs, Object bean, String beanName){...}
- //在bean实例化之后调用
- postProcessAfterInstantiation(Class beanClass, String beanName){..}
-
- }
通过注释内容可以了解,该类在bean初始化前和初始化后调用,于是流程图继续完善:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans
- https://www.springframework.org/schema/beans/spring-beans.xsd
- ">
- <bean class="com.zhufeng.bean.MyInstantiationAwareBeanPostProcessor" />
-
- <bean id="userInfoBean" class="com.zhufeng.bean.UserInfoBean" init-method="init" destroy-method="destroyMethod">
- <!-- setter方法注入 -->
- <property name="userId" value="user1001"/>
- <property name="name" value="月夜烛峰"/>
- </bean>
-
- <bean class="com.zhufeng.bean.MyBeanPostProcessor" />
- <bean class="com.zhufeng.bean.MyBeanFactoryPostProcessor" />
- </beans>
- package com.zhufeng.bean;
-
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.BeanNameAware;
- import org.springframework.beans.factory.DisposableBean;
- import org.springframework.beans.factory.InitializingBean;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.ApplicationContextAware;
-
- /**
- * @ClassName: UserInfoBean
- * @Description 创建userInfoBean
- * @author 月夜烛峰
- * @date 2022/9/6 22:18
- */
- public class UserInfoBean implements InitializingBean, BeanNameAware, DisposableBean, ApplicationContextAware {
-
- private String userId;
- private String name;
-
- public UserInfoBean (){
- System.out.println("2. 调用构造方法");
- }
-
- public String getUserId() {
- return userId;
- }
-
- public void setUserId(String userId) {
- this.userId = userId;
- System.out.println("5. 属性注入 userId");
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- System.out.println("5. 属性注入 name");
- }
-
- @Override
- public String toString() {
- return "UserInfoBean{userId='" + userId +"', name='" + name + "'}";
- }
-
- @Override
- public void setBeanName(String name) {
- System.out.println("6. 调用 BeanNameAware#setBeanName() 方法");
- }
-
- @Override
- public void destroy() throws Exception {
- System.out.println("12. 调用 DisposableBean#destroy() 方法");
- }
-
- public void init() {
- System.out.println("10. 调用 init-method 方法");
- }
-
- public void destroyMethod() {
- System.out.println("13. 调用 destroy-method 方法");
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
- System.out.println("9. 调用 InitializingBean#afterPropertiesSet() 方法");
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- System.out.println("7. 获取 ApplicationContext 上下文信息");
- UserInfoBean userBean = (UserInfoBean) applicationContext.getBean("userInfoBean");
- System.out.println(userBean);
- }
- }
- package com.zhufeng.bean;
-
- import org.springframework.beans.BeansException;
- import org.springframework.beans.PropertyValues;
- import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
-
- /**
- * @ClassName: MyInstantiationAwareBeanPostProcessor
- * @Description TODO
- * @author 月夜烛峰
- * @date 2022/9/6 22:32
- */
- public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
- @Override
- public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
- if ("userInfoBean".equals(beanName)) {
- System.out.println("1. 调用 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation() 方法");
- }
- return null;
- }
-
- @Override
- public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
- if ("userInfoBean".equals(beanName)) {
- UserInfoBean userInfoBean = (UserInfoBean) bean;
- System.out.println("3. 调用 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation() 方法");
- System.out.println(userInfoBean);
- }
- return true;
- }
-
- @Override
- public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
- if ("userInfoBean".equals(beanName)) {
- System.out.println("4. 调用 InstantiationAwareBeanPostProcessor#postProcessProperties() 方法");
- }
- return null;
- }
- }
-
- package com.zhufeng.bean;
-
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanPostProcessor;
-
- /**
- * @ClassName: MyBeanPostProcessor
- * @Description TODO
- * @author 月夜烛峰
- * @date 2022/9/6 22:31
- */
- public class MyBeanPostProcessor implements BeanPostProcessor {
-
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- if ("userInfoBean".equals(beanName)) {
- System.out.println("8. 调用 BeanPostProcessor#postProcessBeforeInitialization() 方法");
- }
- return bean;
- }
-
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- if ("userInfoBean".equals(beanName)) {
- System.out.println("11. 调用 BeanPostProcessor#postProcessAfterInitialization() 方法");
- }
- return bean;
- }
- }
-
- package com.zhufeng.bean;
-
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-
- /**
- * @ClassName: MyBeanFactoryPostProcessor
- * @Description TODO
- * @author 月夜烛峰
- * @date 2022/9/6 22:32
- */
- public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
-
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- System.out.println("0. 调用 BeanFactoryPostProcessor#postProcessBeanFactory() 方法");
- }
- }
-
- package com.zhufeng.bean;
-
- import ch.qos.logback.classic.Level;
- import org.junit.After;
- import org.junit.Before;
- import org.junit.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- /**
- * @ClassName: BeanLifeCycleManager
- * @Description 代码模拟bean生命周期
- * @author 月夜烛峰
- * @date 2022/9/6 22:37
- */
- public class BeanLifeCycleManager {
-
- @Before
- public void before() {
- ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) org.slf4j.LoggerFactory
- .getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
- root.setLevel(Level.INFO);
-
- System.out.println("---bean生命周期开始---");
- }
-
- @After
- public void after() {
- System.out.println("---bean生命周期结束---");
- }
-
- @Test
- public void testBean(){
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- context.getBean("userInfoBean");
- //触发销毁方法
- ((ClassPathXmlApplicationContext) context).close();
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。