Spring Bean 的生命周期

​我们知道 Servlet 拥有明确的生命周期,Spring 容器中的 Bean 也拥有相似的生命周期。Spring Bean 的生命周期从创建Spring容器开始,直到 Spring 容器销毁 Bean。Bean的生命周期由多个特定的生命阶段组成,每个生命阶段都开出了一扇门(提供一些接口),允许外界对 Bean 施加控制。在 Spring 中,可以从两个层面定义 Bean 的生命周期:第一个层面是 Bean 的作用范围;第二个层面是实例化 Bean 时所经历的一系列阶段。下面分别对 BeanFactory 和 ApplicationContext 中 Bean 的生命周期进行分析。

BeanFactory 中 Bean 的生命周期

下图展示了 BeanFactory 中 Bean 的生命周期:

1、当调用者通过 getBean(String name) 方法向容器请求某一个 Bean 时,如果容器注册了 InstantiationAwareBeanPostProcesser 接口,在实例化 Bean 之前,将调用接口的 postProcessBeforeInstantiation() 方法。

​2、根据配置调用 Bean 的构造函数或工厂方法实例化 Bean。

​3、如果容器注册了 InstantiationAwareBeanPostProcesser 接口,在实例化Bean之后,将调用接口的 postProcessAfterInstantiation() 方法。

​4、如果 Bean 配置了属性信息,容器将为 Bean 设置对应的属性值,不过在设置属性之前将调用 InstantiationAwareBeanPostProcesser 接口的 postProcessPropertyValues() 方法。

5、调用 Bean 的属性设置方法设置属性值。

6、如果 Bean 实现了 BeanNameAware 接口,将调用 setBeanName() 方法,将配置文件中该 Bean 对应的名称设置到 Bean 中。

7、如果 Bean 实现了 BeanFactoryAware 接口,将调用 setBeanFactory() 方法,将 BeanFactory 容器实例设置到 Bean 中。

​8、如果 BeanFactory 装配了 BeanPostProcesser 后处理器,将调用 BeanPostProcesser 的 postProcessBeforeInitialization(Object bean, String beanName) 方法对 Bean 进行加工操作。入参 bean 是当前正在操作的 Bean,beanName 是当前 Bean 的配置名,返回的对象是处理后的 Bean。可以使用该方法对 Bean 进行特殊处理,甚至改变 Bean 的行为。BeanPostProcesser 在 Spring 中占有重要地位,Spring 容器所提供的各种神奇的功能(如AOP,动态代理等)都是通过BeanPostProcesser 实施。

​9、如果 Bean 实现了 InitializingBean 接口,将调用接口的 AfterPropertiesSet() 方法。

10、如果在 bean 元素中指定了 init-method 方法,将执行这个方法。

11、BeanPostProcesser 后处理器定义了两个方法,其一在第八步执行,其二是 postProcessAfterInitialization(Object bean, String beanName),在此时调用,容器将再次获得对 Bean 进行加工处理的机会。

12、如果在 bean 元素中指定了 Bean 的作用范围为 scope="prototype",则将 Bean 返回给调用者,调用者负责后续 Bean 的生命周期管理,Spring 不再管理这个 Bean 的生命周期。如果作用范围设置为 scope="singleton"(默认就是单例),则将 Bean 放置到 Spring IoC 容器的缓存池中,并将 Bean 返回给调用者,Spring 继续对这些 Bean 进行后续生命周期管理。

13、对于 scope="singleton" 的 Bean,当容器关闭时,将触发 Spring 对 Bean 的后续生命周期管理工作。首先如果 Bean 实现了DisposableBean 接口,则将调用接口的 afterPropertiesSet() 方法,可以在此编写释放资源、记录日志等操作。

​14、对于 scope="singleton" 的 Bean,如果通过 bean 元素指定了 destroy-method 属性,Spring 将执行 Bean 的这个方法,完成 Bean 资源的释放操作。​

Bean 的完整生命周期从 Spring 容器着手实例化 Bean 开始,直到最终销毁 Bean,这当中经过了许多关键点,每个关键点都涉及特定的方法调用,可以将这些方法大致划分为三类:

• Bean 自身的方法:如调用 Bean 构造函数实例化 Bean,调用 Setter 设置 Bean 的属性值以及调用通过 init-method 和 destroy-method 所指定的方法;

• Bean 级生命周期接口方法:如 BeanNameAware、BeanFactoryAware、InitializingBean 和 DisposableBean,这些接口方法由 Bean 类直接实现。

• 容器级生命周期接口方法:上图中带 ★ 的步骤是由 InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为后处理器,后处理器一般不由 Bean 本身实现,它们独立于 Bean,它们的实现类以 Bean 的形式注册到 Spring 容器中,Spring 容器创建任何 Bean 的时候,这些后处理器都会发生作用,所以这些后处理器的影响是全局的。当然,可以通过合理的编写后处理器,让其仅对感兴趣的 Bean 进行加工处理(比如判断 Bean 的类型,或者 Bean 的名称)。

Bean 级生命周期接口和容器级生命周期接口是个性和共性辩证统一思想的体现,前者解决 Bean 个性化处理的问题;而后者解决容器中某些 Bean 共性化处理的问题。

Spring 容器中可以注册多个后处理器,通过 @Order 注解指定它们生效的顺序,容器将按照特定顺序依次调用这些后处理器。

下面看一下 BeanFactory 中 Bean 的生命周期的例子。

Car.java:

package com.wuychn.beanlifecycle.beanfactory;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;

public class Car implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {

    private String brand;
    private String color;
    private int maxSpeed;

    private BeanFactory beanFactory;
    private String beanName;


    public Car() {
        System.out.println("调用Car()构造函数...");
    }

    // BeanFactoryAware接口方法
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("调用BeanFactoryAware.setBeanFactory()方法...");
        this.beanFactory = beanFactory;
    }

    // BeanNameAware接口方法
    @Override
    public void setBeanName(String beanName) {
        System.out.println("调用BeanNameAware.setBeanName()方法...");
        this.beanName = beanName;
    }

    // DisposableBean接口方法
    @Override
    public void destroy() throws Exception {
        System.out.println("调用DisposableBean.destroy()方法...");
    }

    // InitializingBean接口方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用InitializingBean.afterPropertiesSet()方法...");
    }

    // 通过<bean>的init-method属性指定的初始化方法
    public void myInit() {
        System.out.println("调用init-method指定的myinit()方法,将maxSpeed设置为240...");
        this.maxSpeed = 240;
    }

    // 通过<bean>destroy-method属性指定的销毁方法
    public void myDestroy() {
        System.out.println("调用destroy-myDestroy()方法...");
        this.maxSpeed = 240;
    }

    public void setBrand(String brand) {
        System.out.println("调用setBrand()设置属性...");
        this.brand = brand;
    }

    public String getBrand() {
        return brand;
    }


    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        System.out.println("调用setColor()设置属性...");
        this.color = color;
    }

    public int getMaxSpeed() {
        return maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
        System.out.println("调用setMaxSpeed()设置属性...");
        this.maxSpeed = maxSpeed;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    public String getBeanName() {
        return beanName;
    }

    public void introduce() {
        System.out.println("brand: " + brand + ", color: " + color + ", maxSpeed: " + maxSpeed);
    }


}

Car 类实现了 BeanFactoryAware、BeanNameAware、InitializingBean、DisposableBean 这些 Bean 级生命周期控制接口,定义了 myInit()、和 myDestroy() 方法,以便在配置文件中通过 init-method 和 destroy-method 属性定义初始化和销毁方法。

MyInstantiationAwareBeanPostProcessor.java:

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

import java.beans.PropertyDescriptor;

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    // 在实例化Bean前调用
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        // 仅对 Car Bean进行处理
        if ("car".equals(beanName)) {
            System.out.println("调用MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法...");
        }
        return null;
    }

    // 实例化 Bean 后调用
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        // 仅对 Car Bean进行处理
        if ("car".equals(beanName)) {
            System.out.println("调用MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation方法...");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        return null;
    }

    // 设置某个属性时调用
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        // 仅对 Car Bean进行处理
        if ("car".equals(beanName)) {
            System.out.println("调用MyInstantiationAwareBeanPostProcessor.postProcessProperties方法...");
        }
        return pvs;
    }

}

MyInstantiationAwareBeanPostProcessor 中,仅对名为 car 的 Bean 进行处理。

MyBeanPostProcessor.java:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("car".equals(beanName)) {
            Car car = (Car) bean;
            if (car.getColor() == null) {
                System.out.println("调用MyBeanPostProcessor.postProcessBeforeInitialization方法,color为空,设置为默认黑色");
                car.setColor("黑色");
            }
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("car".equals(beanName)) {
            Car car = (Car) bean;
            if (car.getMaxSpeed() >= 200) {
                System.out.println("调用MyBeanPostProcessor.postProcessAfterInitialization方法,将maxSpeed调整为200");
                car.setMaxSpeed(200);
            }
        }
        return bean;
    }
}

在 MyBeanPostProcessor 类的 postProcessBeforeInitialization() 方法中,首先判断处理的 Bean 是否名为 car,如果是,进一步判断该 Bean 的 color 属性是否为空,如果为空,将该属性设置为“黑色”。在 postProcessAfterInitialization() 方法中,也是只对名为 car 的 Bean 进行处理,判断其 maxSpeed 是否超过最大速度200,如果超过,将其设置为200。

applicationContext.xml 中,Car 的配置如下:

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="car" class="com.wuychn.beanlifecycle.beanfactory.Car"
          init-method="myInit"
          destroy-method="myDestroy">
        <property name="brand" value="奔驰S600L"/>
        <property name="maxSpeed" value="200"/>
    </bean>

</beans>

接下来启动容器,然后注册上面所提供的两个后处理器:

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

public class BeanFactoryLifeCycle {

    public static void startLifeCycle() {
        Resource resource = new PathMatchingResourcePatternResolver().getResource("classpath:applicationContext.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);

        // 注册后处理器
        ((XmlBeanFactory) beanFactory).addBeanPostProcessor(new MyBeanPostProcessor());
        ((XmlBeanFactory) beanFactory).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());

        // 第一次从容器中获取Bean,将处罚容器实例化该Bean,这将引发Bean声明周期的调用
        Car car1 = (Car) beanFactory.getBean("car");
        car1.introduce();
        car1.setColor("白色");

        // 第二次从容器中获取Bean,将直接从缓存池中获取
        Car car2 = (Car) beanFactory.getBean("car");
        car2.introduce();

        // 两次获取到的是统一引用
        System.out.println("car2 == car1 " + (car2 == car1));

        // 关闭容器
        ((XmlBeanFactory) beanFactory).destroySingletons();
    }

    public static void main(String[] args) {
        startLifeCycle();
    }
}

需要强调的是,后处理器的实际调用顺序和注册顺序是无关的,在具有多个后处理器的情况下,必须通过实现的org.springframework.core.Ordered 接口以确定调用顺序。

运行 BeanFactoryLifeCycle,可以看到控制台打印如下:

调用MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation方法...
调用Car()构造函数...
调用MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation方法...
调用MyInstantiationAwareBeanPostProcessor.postProcessProperties方法...
调用setBrand()设置属性...
调用setMaxSpeed()设置属性...
调用BeanNameAware.setBeanName()方法...
调用BeanFactoryAware.setBeanFactory()方法...
调用MyBeanPostProcessor.postProcessBeforeInitialization方法,color为空,设置为默认黑色
调用setColor()设置属性...
调用InitializingBean.afterPropertiesSet()方法...
调用init-method指定的myinit()方法,将maxSpeed设置为240...
调用MyBeanPostProcessor.postProcessAfterInitialization方法,将maxSpeed调整为200
调用setMaxSpeed()设置属性...
brand: 奔驰S600L, color: 黑色, maxSpeed: 200
调用setColor()设置属性...
brand: 奔驰S600L, color: 白色, maxSpeed: 200
car2 == car1 true
调用DisposableBean.destroy()方法...
调用destroy-myDestroy()方法...

仔细观察输出的信息,发现它验证了前面所介绍故的 Bean 生命周期的过程。最后通过 destroySingletons() 方法关闭了容器,由于 Car 实现了销毁接口并指定了销毁方法,所以容器将触发调用这两个方法。

了解了 BeanFactory 中 Bean 的生命周期之后,我们来看看这个过程中涉及到的一些接口。

BeanNameAware

BeanNameAware 接口的源码如下:

public interface BeanNameAware extends Aware {
    void setBeanName(String var1);
}

这个接口的作用是,让 Bean 获取自己在 BeanFactory 配置中的名字。就像上面的 Car 类,它实现了 BeanNameAware 接口,并重写了 setBeanName(String beanName) 方法,将配置的 beanName 设置到 Car 的成员变量中,Spring 会自动调用这个接口的方法。

BeanFactoryAware

BeanFactoryAware 接口的源码如下:

public interface BeanFactoryAware extends Aware {
    void setBeanFactory(BeanFactory var1) throws BeansException;
}

这个接口的作用是,可以在 Bean 中注入 Spring 的容器 BeanFactory,让 Bean 拥有访问 Spring 容器的能力,注入了 BeanFactory 之后,Bean 就可以访问容器中任意的其他 Bean 了。

InitializingBean

InitializingBean 接口的源码如下:

public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

InitializingBean 接口为 bean 提供了初始化方法的方式,它只有一个 afterPropertiesSet() 方法,凡是实现该接口的类,在初始化 bean 的时候都会执行该方法。我们知道,init-method 也可以配置 Bean 的初始化方法,那么这二者有什么区别呢?通过分析上例中的执行结果,可知如果某个类同时实现了 InitializingBean 接口和指定了 init-method 初始化方法,那么 Spring 会先调用 InitializingBean.afterPropertieSet() 方法,然后再调用 init-method 指定的方法。

DisposableBean

DisposableBean 的源码如下:

public interface DisposableBean {
    void destroy() throws Exception;
}

如果某个类实现了 DisposableBean 接口,那么 Spring 容器释放该 bean 之后将调用这个接口的 destroy() 方法。我们知道,destroy-method 属性也可以知道 Bean 销毁时调用的方法,那么这二者有什么区别呢?通过分析上例的执行结果可知,DisposableBean.destroy() 方法会在 destroy-method 指定的方法之前调用。

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor 的源码如下:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        return null;
    }

    /** @deprecated */
    @Deprecated
    @Nullable
    default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        return pvs;
    }
}

InstantiationAwareBeanPostProcessor 接口继承自 BeanPostProcessor 接口,InstantiationAwareBeanPostProcessor 接口的主要作用在于在目标对象的实例化前后以及属性设置前做一些操作,可以分析上例的执行结果得到结论。这个接口一般不由 Bean 去实现,而是单独提供一个实现类并注册到 Spring 容器中,对于 BeanFactory 需要手动注册,而 ApplicationContext 则会自动扫描容器中该接口的实现而自动注册,这个接口的作用范围是全局的,即所有 Bean 在实例化前后都会执行相应的操作。容器中可以有多个 InstantiationAwareBeanPostProcessor 接口的实现,需要通过 Order 接口指定它们的执行顺序。

BeanPostProcesser

BeanPostProcesser 接口的源码如下:

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

这个接口的作用是,在 Bean 初始化(注意区分初始化和实例化,实例化是调用构造函数,初始化是调用 InitializingBean.afterProperties() 和 init-method 指定的方法)前后做一些操作。如果想在 Bean 初始化前后做一些操作,比如修改 Bean 的某些属性,那么可以提供一个类实现 BeanPostProcesser 接口并将其注册到 Spring 容器中。这个接口一般不由 Bean 去实现,而是单独提供一个实现类并注册到 Spring 容器中,对于 BeanFactory 需要手动注册,而 ApplicationContext 则会自动扫描容器中该接口的实现而自动注册,这个接口的作用范围是全局的,即所有 Bean 在初始化前后都会执行相应的操作,当然可以通过编码的方式,选择对一些感兴趣的 Bean 进行处理,就像上例中只对名为 car 的 Bean 进行操作一样。容器中可以有多个 BeanPostProcessor 接口的实现,需要通过 Order 接口指定它们的执行顺序。

ApplicationContext中Bean的生命周期

ApplicationContext 中 Bean 的生命周期和在 BeanFactory 中生命周期类似,不同是,BeanFactory 启动时不会创建所有单例的 Bean,而是等到第一次调用某个 Bean 时创建,而 ApplicationContext 则会在容器启动时创建所有单例的 Bean,因此 ApplicationContext 的启动会比 BeanFactory 稍慢,但后续不会有“第一次惩罚”的问题,另外,如果 Bean 实现 ApplicationContextAware 接口,会增加一个调用该接口方法 setApplicationContext() 的步骤:

 

此外,如果配置文件中声明了工厂后处理器接口 BeanFactoryPostProcessor 的实现类,则应用上下文在装载配置文件之后、初始化 Bean 实例之前将调用这些 BeanFactoryPostProcessor 对配置信息进行加工处理。Spring 框架提供了多个工厂后处理器,比如 CustomEditorConfigurer、PopertyPlaceholderConfigurer 等。如果配置文件中定义了多个工厂后处理器,最好让它们实现 Ordered 接口,以便 Spring 以确定的顺序调用它们。工厂后处理器是容器级的,仅在应用上下文初始化时调用一次,其目的是完成一些配置文件的加工处理工作。

ApplicationContext 和 BeanFactory 另一个最大的不同之处在于:前者会利用 Java 反射机制自动识别出配置文件中定义的 BeanPostProcessor、InstantiationAwareBeanPostProcessor 和 BeanFactoryPostProcessor,并自动将它们注册到应用上下文中,而后者需要在代码中通过手工调用 addBeanPostProcessor() 方法进行注册。在 ApplicationContext 中,我们只需要在配置文件中通过 <bean> 定义工厂后处理器和 Bean 后处理器,它们就会按预期的方式运行(在实际应用中,提供一个相应的后处理器实现类,使用 @Component 注解标识即可生效)。

来看一个使用工厂后处理器的实例,假设我们希望对配置文件中 car 的 brand 配置属性进行调整,则可以编写一个如下的工厂后处理器:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    // 对car<bean>的brand属性配置信息进行修改
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("car");
        beanDefinition.getPropertyValues().addPropertyValue("brand", "宾利慕尚");
        System.out.println("调用MyBeanFactoryPostProcessor.postProcessBeanFactory方法...");
    }
}

ApplicationContext在启动时,将首先为配置文件中每个 <bean> 生成一个 BeanDefinition 对象,BeanDefinition 是 <bean> 在Spring 容器中的内部表示。当配置文件中所有的 <bean> 都被解析成 BeanDefinition 时,ApplicationContext 将调用工厂后处理器的方法,因此我们有机会通过程序的方式调整 Bean 的配置信息。在这里,我们将 car 对应的 BeanDefinition 进行调整,修改其 brand 属性值,下面是具体的配置:

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 这个Bean的brand属性值将被工厂后处理器改掉 -->
    <bean id="car" class="com.wuychn.beanlifecycle.beanfactory.Car"
          init-method="myInit"
          destroy-method="myDestroy">
        <property name="brand" value="奔驰S600L"/>
        <property name="maxSpeed" value="200"/>
    </bean>

    <!-- 注册Bean后处理器,这个后处理器会自动被 ApplicationContext 注册 -->
    <bean id="myBeanPostProcessor"
          class="com.wuychn.beanlifecycle.beanfactory.MyBeanPostProcessor"/>

    <!-- 注册工厂后处理器,这个后处理器会自动被 ApplicationContext 注册 -->
    <bean id="myBeanFactoryPostProcessor"
          class="com.wuychn.beanlifecycle.applicationcontext.MyBeanFactoryPostProcessor"/>

</beans>

最后,ApplicationContextLifeCycle 类如下:

package com.wuychn.beanlifecycle.applicationcontext;

import com.wuychn.beanlifecycle.beanfactory.Car;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ApplicationContextLifeCycle {

    public static void startLifeCycle() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        // 第一次从容器中获取Bean,将处罚容器实例化该Bean,这将引发Bean声明周期的调用
        Car car1 = (Car) applicationContext.getBean("car");
        car1.introduce();
        car1.setColor("白色");

        // 第二次从容器中获取Bean,将直接从缓存池中获取
        Car car2 = (Car) applicationContext.getBean("car");
        car2.introduce();

        // 两次获取到的是统一引用
        System.out.println("car2 == car1 " + (car2 == car1));

        // 关闭容器
        ((ClassPathXmlApplicationContext) applicationContext).destroy();
    }

    public static void main(String[] args) {
        startLifeCycle();
    }
}

运行 ApplicationContextLifeCycle,可以看到 car Bean 的 brand 属性被成功修改了:

调用MyBeanFactoryPostProcessor.postProcessBeanFactory方法...
调用Car()构造函数...
调用setBrand()设置属性...
调用setMaxSpeed()设置属性...
调用BeanNameAware.setBeanName()方法...
调用BeanFactoryAware.setBeanFactory()方法...
调用MyBeanPostProcessor.postProcessBeforeInitialization方法,color为空,设置为默认黑色
调用setColor()设置属性...
调用InitializingBean.afterPropertiesSet()方法...
调用init-method指定的myinit()方法,将maxSpeed设置为240...
调用MyBeanPostProcessor.postProcessAfterInitialization方法,将maxSpeed调整为200
调用setMaxSpeed()设置属性...
brand: 宾利慕尚, color: 黑色, maxSpeed: 200
调用setColor()设置属性...
brand: 宾利慕尚, color: 白色, maxSpeed: 200
car2 == car1 true
18:28:43.864 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@4f4a7090, started on Wed Dec 12 18:28:43 CST 2018
调用DisposableBean.destroy()方法...
调用destroy-myDestroy()方法...

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值