spring bean 的生命週期的點點滴滴

一、緒論

 

這篇博文的代碼其實很早就有了(在看《精通spring4.x企業應用開發實踐》學習記錄的),只是我沒有把它寫成博文,今天突然想去翻翻,找半天才找到,所以我在此記錄一下,否則今後再想去看又找不到了,在此非常感謝作者,讓我看到了這麼細緻的spring開發書籍。本篇也是在作者書籍當中的代碼自己敲了過來,學習學習。

二、spring  Bean介紹

spring的bean實例化會經歷多個階段,每個階段都爲bean處理不同的邏輯和控制

三,spring Bean 的初始化過程(生命週期)

1、我在這引入書中的一張圖

這張圖可謂是概括了bean的生命週期全部內容,堪稱經典。

我們可能會想那spring 會在什麼時候去實例化bean呢?別慌,下面就行答案(嘿嘿~~~)

這裏我百度的,地址:https://www.cnblogs.com/zhaoxinshanwei/p/8856318.html

Spring什麼時候實例化bean,首先要分2種情況 
  第一:如果你使用BeanFactory作爲Spring Bean的工廠類,則所有的bean都是在第一次使用該Bean的時候實例化 
  第二:如果你使用ApplicationContext作爲Spring Bean的工廠類,則又分爲以下幾種情況: 
       (1):如果bean的scope是singleton的,並且lazy-init爲false(默認是false,所以可以不用設置),則ApplicationContext啓動的時候就實例化該Bean,並且將實例化的Bean放在一個map結構的緩存中,下次再使用該Bean的時候,直接從這個緩存中取 
       (2):如果bean的scope是singleton的,並且lazy-init爲true,則該Bean的實例化是在第一次使用該Bean的時候進行實例化 
       (3):如果bean的scope是prototype的,則該Bean的實例化是在第一次使用該Bean的時候進行實例化

 

2、代碼實現之生命週期測試階段(代碼來自書籍中的測試)

定義bean 並且  implements Serializable,BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean

完整代碼:

package com.bean.lifecycle;

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

import java.io.Serializable;

/**
 * bean生命週期(bean級)
 */
public class Car implements Serializable,BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean {

    private String name;
    private String color;
    private int maxSpeed;

    private BeanFactory beanFactory;
    private String benaName;

    public Car() {
        System.out.println("調用 Car 的 構造函數。。");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("調用 setName()設置屬性");
        this.name = name;
    }

    public String getColor() {
        return color;
    }

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

    public int getMaxSpeed() {
        return maxSpeed;
    }

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


    //2、BenaFactoryAware接口方法
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("調用BenaFactoryAware接口的setBeanFactory()方法");
        this.beanFactory=beanFactory;
    }
    //3、BeanNameAware接口方法
    @Override
    public void setBeanName(String benaName) {
        System.out.println("調用BeanNameAware接口方法接口的setBeanName()方法");
        this.benaName=benaName;

    }
    //4、InitializingBean接口方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("調用InitializingBean接口方法接口的afterPropertiesSet()方法");
    }
    //5、DisposableBean接口方法
    @Override
    public void destroy() throws Exception {
        System.out.println("調用DisposableBean接口方法接口的destroy()方法");
    }
    //6、通過<bean>的init-method屬性指定初始化方法
    public void myInit(){
        System.out.println("調用init-method所指定的myInit()方法,並且將v屬性設置爲10000");
        this.maxSpeed=10000;
    }
    //7、通過<bean>的destroy-method屬性指定初始化方法
    public void myDestroy(){
        System.out.println("調用destroy-method所指定的myDestroy()方法");
    }


    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", maxSpeed=" + maxSpeed +
                ", beanFactory=" + beanFactory +
                ", benaName='" + benaName + '\'' +
                '}';
    }
}

定義一個後置處理器

MyInstantiationAwareBeanPostProcessor 並且繼承 InstantiationAwareBeanPostProcessorAdapter 實現 Ordered

完整代碼:

package com.bean.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.core.Ordered;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;

/**
 * 後處理器(InstantiationAwareBeanPostProcessorAdapter 最終還是實現的是 BeanPostProcessor 接口)
 */
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements Ordered{

    public MyInstantiationAwareBeanPostProcessor() {
        super();
    }

    @Override
    public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
        return super.predictBeanType(beanClass, beanName);
    }

    @Override
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
        return super.determineCandidateConstructors(beanClass, beanName);
    }

    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        return super.getEarlyBeanReference(bean, beanName);
    }

    //1、接口方法,實例化bean前調用
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        //僅對容器中的car bena處理
        if("car".equals(beanName)){
            System.out.println("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation");
        }

        return null;
    }
    //2、接口方法,在bean實例化後調用
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
       //2-1、僅對容器中的car baen處理
        if("car".equals(beanName)){
            System.out.println("InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation");
        }
        return true;
    }
    //3、接口方法,在設置某個屬性值時調用
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        //3-1、僅對容器中的car baen處理
        if("car".equals(beanName)){
            System.out.println("InstantiationAwareBeanPostProcessor.postProcessPropertyValues");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return super.postProcessAfterInitialization(bean, beanName);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

注意:InstantiationAwareBeanPostProcessorAdapter 最終也是實現BeanPostProcessor接口

我們再來定義一個  後處理器 MyBeanPostProcessor

完整代碼如下:

package spring.lifecycle;

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

/**
 * 後處理器
 */
public class MyBeanPostProcessor implements BeanPostProcessor,Ordered {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       if(beanName.equals("car")){
           Car car= (Car) bean;
           if(car.getName()==null||car.getName()==""){
               System.out.println("調用MyBeanPostProcessor的postProcessBeforeInitialization方法,並且設置 car 的名稱爲 ‘奧迪A1’");
               car.setName("奧迪A1");
           }
       }
       return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("car")){
            Car car= (Car) bean;
            if(car.getMaxSpeed()>=500){
                System.out.println("調用MyBeanPostProcessor的postProcessAfterInitialization方法,並且設置 car 的MaxSpeed 爲500");
                car.setMaxSpeed(500);
            }
        }
        return bean;
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

 

定義一個  工廠 後處理器   

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor

 

完整代碼如下:

package spring.lifecycle;


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 {

    //1、對car 的color 屬性進行“偷樑換柱”的加工操作
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
        BeanDefinition beanDefinition = bf.getBeanDefinition("car");
        System.out.println("原來的color:"+beanDefinition.getPropertyValues().getPropertyValue("color").getValue());
        System.out.println("原來的maxSpeed:"+beanDefinition.getPropertyValues().getPropertyValue("maxSpeed").getValue());
        beanDefinition.getPropertyValues().addPropertyValue("color",
                "粉紅色。。。@@@");
        System.out.println("調用BeanFactoryPostProcessor接口的postProcessBeanFactory()方法");

    }
}

 

最後來測試

package spring.lifecycle;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

/**
 * 讓容器裝載配置文件,然後分別註冊鎖提供的兩個後置處理器
 */
public class BeanLifeCycle {

    private static void lifeCycleInBeanFactory(){
        //1、下面兩句是裝載配置文件並且啓動容器
//        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("calsspath:applicationContext.xml");
        Resource classPathResource = new ClassPathResource("applicationContext.xml");
        BeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) defaultListableBeanFactory);
        reader.loadBeanDefinitions(classPathResource);

        //2、向容器註冊MyBeanPostProcessor後處理器
        ((ConfigurableBeanFactory)defaultListableBeanFactory).addBeanPostProcessor(new MyBeanPostProcessor());

        //3、向容器註冊MyInstantiationAwareBeanPostProcessor後處理器
        ((ConfigurableBeanFactory)defaultListableBeanFactory).addBeanPostProcessor(
                new MyInstantiationAwareBeanPostProcessor());

        //4、第一次從容器中獲取car ,將觸發容器實例化該bean,這將引發bean生命週期的方法調用
        Car car = defaultListableBeanFactory.getBean("car", Car.class);
        car.setColor("紅色");


        //5、第二次從容器中獲取car,直接從緩存池中獲取
        Car car1 = defaultListableBeanFactory.getBean("car", Car.class);
        //6、查看car與car1是否爲同一個對象
        System.out.println("(car==car1) :"+(car==car1));

        //7、關閉容器
        ((ConfigurableBeanFactory) defaultListableBeanFactory).destroySingletons();

    }

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

 

運行結果:

總結:ApplicationContext是自動註冊後置處理器,而beanFactor需要手動調用addBeanPostProcessor方法註冊

代碼中都有註釋,到此完畢!!!

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章