spring BeanFactory及ApplicationContext中Bean的生命週期

spring bean 的生命週期java

spring BeanFactory及ApplicationContext在讀取配置文件後、實例化bean先後、設置bean的屬性先後這些點均可以經過實現接口添加咱們本身的邏輯spring


spring BeanFactory中Bean的生命週期緩存

demo1 框架

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>4.3.16.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.3.16.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>4.3.16.RELEASE</version>
    </dependency>
  </dependencies>
pom.xml
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;

/**
 * BeanFactoryAware 覺察到
 * InitializingBean 初始化
 * Disposable 一次性的,可任意處理的; 用後就拋棄的
 *
 * BeanFactoryAware、BeanNameAware、InitializingBean、DisposableBean都是Bean級的生命週期控制接口
 */
public class Car implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
    // 品牌
    private String brand;
    // 顏色
    private String color;
    // 最快速度
    private int maxSpeed;

    public Car() {
        System.out.println("構造方法執行");
    }

    public void setBrand(String brand) {
        System.out.println("setBrand方法執行");
        this.brand = brand;
    }
    public String getColor() {
        return this.color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getMaxSpeed() {
        return maxSpeed;
    }

    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }

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

    private BeanFactory beanFactory;
    @Override
    // 實現BeanFactoryAware須要重寫的惟一方法
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("調用BeanFactoryAware接口定義的setBeanFactory方法");
        this.beanFactory = beanFactory;
    }

    private String beanName;
    @Override
    // 實現BeanNameAware須要重寫的惟一方法
    public void setBeanName(String beanName) {
        System.out.println("調用BeanNameAware接口定義的setBeanName方法");
        this.beanName = beanName;
    }

    @Override
    // 實現InitializingBean須要重寫的惟一方法
    public void afterPropertiesSet() throws Exception {
        System.out.println("調用InitializingBean接口定義的afterPropertiesSet方法");
    }

    @Override
    // 實現DisposableBean須要重寫的惟一方法
    public void destroy() throws Exception {
        System.out.println("調用DisposableBean接口定義的destroy方法");
    }

    // 經過<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-method指定的myDestroy方法");
    }
}
Car.java
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

import java.beans.PropertyDescriptor;

public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
    /**
     * 在實例化Bean前調用,僅對容器中的car Bean處理
     *
     * 父類實現了接口 SmartInstantiationAwareBeanPostProcessor,
     * SmartInstantiationAwareBeanPostProcessor 又繼承了接口 InstantiationAwareBeanPostProcessor
     * InstantiationAwareBeanPostProcessor 又繼承了 BeanPostProcessor
     * 有方法postProcessBeforeInstantiation
     */
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if ("car".equals(beanName)) {
            System.out.println("InstantiationAwareBeanPostProcessor 接口的 postProcessBeforeInstantiation 方法執行");
        }
        return null;
    }

    /**
     * 在實例化Bean後調用,僅對容器中的car Bean處理
     *
     * 同上,InstantiationAwareBeanPostProcessor 有方法 postProcessAfterInstantiation
     */
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("car".equals(beanName)) {
            System.out.println("InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation 方法執行");
        }
        return true;
    }

    /**
     * 在設置某個屬性時調用,僅對car Bean的品牌屬性值進行處理,還能夠經過pds入參進行過濾
     *
     * 同上,InstantiationAwareBeanPostProcessor 有方法 postProcessPropertyValues
     */
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        if ("car".equals(beanName)) {
            System.out.println("InstantiationAwareBeanPostProcessor 接口的 postProcessPropertyValues 方法執行");
        }
        return pvs;
    }
}
MyInstantiationAwareBeanPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * processor 加工,處理
 * BeanPostProcessor後處理器在spring框架中佔有重要的地位,這是容器對Bean進行後續加工處理的切入點;
 * spring提供的動態代理、AOP都是經過BeanPostProcessor實現的
 */
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("car")) {
            Car car = (Car)bean;
            if (car.getColor() == null) {
                System.out.println("調用接口BeanPostProcessor的postProcessBeforeInitialization方法," +
                        "color爲空,設置爲默認黑色");
                car.setColor("黑色");
            }
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("car")) {
            Car car = (Car)bean;
            if (car.getMaxSpeed() >= 200) {
                System.out.println("調用接口BeanPostProcessor的postProcessAfterInitialization方法," +
                        "將maxSpeed調整爲200");
                car.setMaxSpeed(200);
            }
        }
        return bean;
    }
}
MyBeanPostProcessor
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       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="Car" init-method="myInit" destroy-method="myDestroy"
    p:brand="寶馬373" p:maxSpeed="220"/>

</beans>
my.xml
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;

/**
 * 測試類
 */
public class BeanLifeCycle {

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

    private static void lifeCycleBeanFactory() {
        // 裝載配置文件
        ClassPathResource resource = new ClassPathResource("my.xml");

        // 啓動容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory) beanFactory);
        reader.loadBeanDefinitions(resource);

        // 向容器中註冊MyBeanPostProcessor後處理器
        ((ConfigurableBeanFactory)beanFactory).addBeanPostProcessor(new MyBeanPostProcessor());
        // 向容器中註冊MyInstantiationAwareBeanPostProcessor後處理器
        ((ConfigurableBeanFactory)beanFactory).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());

        // 第一次從容器中獲取car,將觸發容器實例化這個Bean,這將引起Bean生命週期方法的調用
        Car car1 = (Car)beanFactory.getBean("car");
        car1.introduce();
        car1.setColor("紅色");

        // 第二次從容器中獲取car,直接從緩存池中獲取
        Car car2 = (Car) beanFactory.getBean("car");

        // 查看car1和car2是否指向同一引用
        System.out.println("car1==car2:" + (car1 == car2));

        ((DefaultListableBeanFactory)beanFactory).destroySingletons();
    }
}
測試類
1、InstantiationAwareBeanPostProcessor 接口的 postProcessBeforeInstantiation 方法執行
構造方法執行
2、InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation 方法執行
3、InstantiationAwareBeanPostProcessor 接口的 postProcessPropertyValues 方法執行
setBrand方法執行
4、調用BeanNameAware接口定義的setBeanName方法
5、調用BeanFactoryAware接口定義的setBeanFactory方法
6、調用接口BeanPostProcessor的postProcessBeforeInitialization方法,color爲空,設置爲默認黑色
7、調用InitializingBean接口定義的afterPropertiesSet方法
八、調用init-method指定的myInit方法,將maxSpeed設置爲240
9、調用接口BeanPostProcessor的postProcessAfterInitialization方法,將maxSpeed調整爲200
brand:寶馬373;color:黑色;maxSpeed:200
car1==car2:true
10、調用DisposableBean接口定義的destroy方法
十一、調用destroy-method指定的myDestroy方法

輸出分析:
在一個bean實例化之間以後,調用一、2。
1的方法入參是Class<?> beanClass, String beanName,分別對應bean的class和id
2的方法入參是Object bean, String beanName,分別對應實例化好的bean和bean的id

在屬性填充前,調用3。
3的方法入參是PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName
pvs裏封裝着屬性值,pds裏封裝着屬性名,bean是實例化後的bean,beanName是bean的id

屬性填充後,調用四、5。
4的方法入參是String beanName,能夠把beanName也就是bean的id緩存起來,保存爲一個成員變量
5的方法入參是BeanFactory beanFactory,能夠把beanFactory緩存起來,保存爲一個成員變量

在bean初始化以前以後調用六、9,這是BeanPostProcessor的方法,能夠修改屬性值,能夠添加AOP
7、8是初始化方法
十、11是銷燬方法
運行輸出分析

其中的BeanPostProcessor接口很是重要,spring的動態代理、AOP都是經過實現這個接口而爲bean添加行爲的ide


spring ApplicationContext中Bean的生命週期post

Spring Bean在ApplicationContext和BeanFactory中的生命週期相似。測試

不一樣的是,若是Bean實現了org.springframework.context.ApplicationContextAware接口,會增長一個調用該接口方法setApplicationContext()的步驟。ui

而且多了BeanFactoryPostProcessor接口,若是實現了該接口,ApplicationContext在裝載配置文件以後、實例化Bean以前將調用該實現類的方法,對配置信息進行加工處理。Spring框架提供了多個工廠後處理器,如CustomEditorConfigurer、PopertyPlaceholderConfigurer等。工廠後處理器是容器級的,僅在ApplicationContext初始化時調用一次。this

ApplicationContext在啓動時,將首先爲配置文件中的每一個<bean>生成一個BeanDefinition對象,BeanDefinition是<bean>在Spring容器中的內部表示。當配置文件中全部的<bean>都被解析爲BeanDefinition時,ApplicationContext將調用工廠後處理器的方法,因些,咱們有機會經過程序的方式調整Bean的配置信息。spa

ApplicationContext和BeanFactory的一個最大的不一樣之處在於,前者會利用Java反射機制自動識別出配置文件中定義的BeanPostProcessor、InstantiationAwareBeanPostProcessor及BeanFactoryPostProcessor,並自動將它們註冊到ApplicatContext中(在ApplicatContext中,只需在配置文件中經過<bean>定義工廠後處理器和Bean後處理器,它們就會按預期的方式運行);然後者須要在代碼中手工調用addBeanProcessor()方法進行註冊。

demo2——BeanFactoryPostProcessor
還使用demo1那個例子的代碼,添加了MyBeanFactoryPostProcessor的實現、修改了my.xml、修改了測試類 

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 {
    @Override
    // 實現BeanFactoryPostProcessor須要重寫的惟一方法
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("car");
        beanDefinition.getPropertyValues().addPropertyValue("brand", "吉利博瑞");
        System.out.println("調用BeanFactoryPostProcessor的postProcessBeanFactory方法");
    }
}
MyBeanFactoryPostProcessor 
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       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="Car" init-method="myInit" destroy-method="myDestroy"
    p:brand="寶馬373" p:maxSpeed="220"/>

    <bean class="MyBeanPostProcessor"/>

    <bean class="MyInstantiationAwareBeanPostProcessor"/>

    <bean class="MyBeanFactoryPostProcessor"/>

</beans>
my.xml 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 測試類
 */
public class BeanLifeCycle {

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

    private static void lifeCycleBeanFactory() {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:my.xml");

        Car car1 = (Car)context.getBean("car");
        car1.introduce();
        car1.setColor("紅色");

        // 第二次從容器中獲取car,直接從緩存池中獲取
        Car car2 = (Car) context.getBean("car");

        // 查看car1和car2是否指向同一引用
        System.out.println("car1==car2:" + (car1 == car2));

        ((ClassPathXmlApplicationContext)context).destroy();
    }
}
測試類

demo3——BeanFactoryPostProcessor
經過程序的方式調整Bean的配置信息

      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.16.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.16.RELEASE</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>4.3.16.RELEASE</version>
      </dependency>
pom.xml
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Driver {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("my.xml");
        Boss boss1 = context.getBean("boss1", Boss.class);
        Boss boss2 = context.getBean("boss2", Boss.class);

        System.out.println(boss1);
        System.out.println(boss2);
    }
}
class Boss {
    private Car car;

    public Car getCar() {
        return car;
    }

    public void setCar(Car car) {
        this.car = car;
    }
}
class Car { }
View Code
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

/**
 * BeanPostProcessor
 * Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
 * Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
 *
 * BeanFactoryPostProcessor
 * void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
 *
 * BeanPostProcessor和BeanFactoryPostProcessor是兩個不一樣的接口:
 * BeanPostProcessor是在Bean實例化後、屬性設置後執行,是Spring AOP 的賴以實現的基礎;
 * BeanFactoryPostProcessor是WebApplicationContext讀取配置文件後,尚未初始化任何實例時運行,
 * 能夠用來修改配置文件
 *
 */
public class UserServiceFactoryBean implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
        // 把ConfigurableListableBeanFactory轉化爲DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) bf;
        // 經過BeanDefinitionBuilder建立bean定義
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Boss.class);
        // 設置屬性userDao,此屬性引用已經定義的bean:car
        beanDefinitionBuilder.addPropertyReference("car", "car");
        // 註冊bean定義
        beanFactory.registerBeanDefinition("boss1", beanDefinitionBuilder.getRawBeanDefinition());
        // 直接註冊一個bean實例
        beanFactory.registerSingleton("boss2", new Boss());
    }
}
View Code
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       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="Car"/>

    <bean class="UserServiceFactoryBean"/>

</beans>
View Code
相關文章
相關標籤/搜索