Spring Bean的生命週期(非常詳細)

轉載地址: http://www.cnblogs.com/zrtqsk/p/3735273.html

Spring作爲當前Java最流行、最強大的輕量級框架,準確的瞭解Spring Bean的生命週期非常必要。
通常使用ApplicationContext作爲Spring容器。下面講的也是 ApplicationContext中Bean的生命週期。實際上BeanFactory也是差不多,但是處理器需手動註冊。

一、生命週期流程圖:

  Spring Bean的完整生命週期從創建Spring容器開始,直到最終Spring容器銷燬Bean,包含了下面一系列關鍵點,若容器註冊了以下各種接口,那麼程序將會按照下面流程進行:

 

 二、各種接口方法分類

 Bean的完整生命週期經歷了各種方法調用,這些方法可以劃分爲以下幾類:
    1、Bean自身的方法:這個包括了Bean本身調用的方法和通過配置文件中<bean>的init-method和destroy-method指定的方法;
    2、Bean級生命週期接口方法:這個包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這些接口的方法;
    3、容器級生命週期接口方法:這個包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 這兩個接口實現,一般稱它們的實現類爲“後處理器”。
    4、工廠後處理器接口方法:這個包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工廠後處理器接口的方法。工廠後處理器也是容器級的。在應用上下文裝配配置文件之後立即調用。

三、驗證demo

我們用一個簡單的Spring Bean來演示一下Spring Bean的生命週期。

1、首先是一個簡單的Spring Bean,調用Bean自身的方法和Bean級生命週期接口方法,爲了方便演示,它實現了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這4個接口,同時有2個方法,對應配置文件中<bean>的init-method和destroy-method。如下:

package com.atguigu.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;

/**
 * Bean級生命週期接口方法
 */
public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {

    private String name;
    private String address;
    private int phone;

    private BeanFactory beanFactory;
    private String beanName;

    public Person() {
        System.out.println("【構造器】調用Person的構造器實例化");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("【注入屬性】注入屬性name");
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        System.out.println("【注入屬性】注入屬性address");
        this.address = address;
    }

    public int getPhone() {
        return phone;
    }

    public void setPhone(int phone) {
        System.out.println("【注入屬性】注入屬性phone");
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Person [address=" + address + ", name=" + name + ", phone=" + phone + "]";
    }

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

    // 這是BeanNameAware接口方法
    @Override
    public void setBeanName(String arg0) {
        System.out.println("【BeanNameAware接口】調用BeanNameAware.setBeanName()");
        this.beanName = arg0;
    }

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

    // 這是DiposibleBean接口方法
    @Override
    public void destroy() throws Exception {
        System.out.println("【DiposibleBean接口】調用DiposibleBean.destory()");
    }

    // 通過<bean>的init-method屬性指定的初始化方法
    public void myInit() {
        System.out.println("【init-method】調用<bean>的init-method屬性指定的初始化方法");
    }

    // 通過<bean>的destroy-method屬性指定的初始化方法
    public void myDestory() {
        System.out.println("【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法");
    }
}

2、接下來BeanPostProcessor接口的方法,BeanPostProcessor接口包括2個方法postProcessAfterInitialization和postProcessBeforeInitialization,這兩個方法的第一個參數都是要處理的Bean對象,第二個參數都是Bean的name。返回值是要處理的Bean對象。如下:

package com.atguigu.test;

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

public class MyBeanPostProcessor implements BeanPostProcessor {

    public MyBeanPostProcessor() {
        super();
        System.out.println("這是BeanPostProcessor實現類構造器!!");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改!");
        return bean;
    }
}

3、InstantiationAwareBeanPostProcessor 接口本質是BeanPostProcessor的子接口,一般我們繼承Spring爲其提供的適配器類InstantiationAwareBeanPostProcessorAdapter來使用它,如下:

package com.atguigu.test;

import java.beans.PropertyDescriptor;

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

public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

    public MyInstantiationAwareBeanPostProcessor() {
        super();
        System.out.println("這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!");
    }

    // 接口方法、實例化Bean之前調用
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法");
        return super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    // 接口方法、實例化Bean之後調用
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor調用postProcessAfterInstantiation方法");
        return super.postProcessAfterInstantiation(bean, beanName);
    }

    // 接口方法、設置某個屬性時調用
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法");
        return super.postProcessPropertyValues(pvs, pds, bean, beanName);
    }

    // 接口方法、初始化Bean之前調用
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor調用postProcessBeforeInitialization方法");
        return super.postProcessBeforeInitialization(bean, beanName);
    }

    // 接口方法、初始化Bean之後調用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法");
        return super.postProcessAfterInitialization(bean, beanName);
    }
}

4、工廠後處理器接口方法,如下:

package com.atguigu.test;

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 {

    public MyBeanFactoryPostProcessor() {
        super();
        System.out.println("這是BeanFactoryPostProcessor實現類構造器!!");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryPostProcessor調用postProcessBeanFactory方法");
        BeanDefinition bd = beanFactory.getBeanDefinition("person");
        // 此處會調用一次setPhone()方法
        bd.getPropertyValues().addPropertyValue("phone", "110");
    }
}

5、添加配置類,如下:

package com.atguigu.test;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ConfigBean {

    @Bean(initMethod = "myInit", destroyMethod = "myDestroy")
    public Person person() {
        Person person = new Person();
        person.setAddress("廣州");
        person.setName("張三");
        person.setPhone("15900000000");
        return person;
    }

    @Bean
    public MyBeanFactoryPostProcessor myBeanFactoryPostProcessor() {
        return new MyBeanFactoryPostProcessor();
    }

    @Bean
    public MyBeanPostProcessor myBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }

    @Bean
    public MyInstantiationAwareBeanPostProcessor myInstantiationAwareBeanPostProcessor() {
        return new MyInstantiationAwareBeanPostProcessor();
    }
}

6、測試類,關閉容器使用的是實際是AbstractApplicationContext的鉤子方法,如下:

package com.atguigu.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class BeanLifeCycle {

    public static void main(String[] args) {
        System.out.println("現在開始初始化容器");
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigBean.class);
        System.out.println("容器初始化成功");
        Object person = applicationContext.getBean("person");
        System.out.println(person);
        System.out.println("現在開始關閉容器!");
        ((AnnotationConfigApplicationContext) applicationContext).registerShutdownHook();
    }
}

7. 測試結果:

// o.s.b.f.s.D == org.springframework.beans.factory.support.DefaultListableBeanFactory
// o.s.c.a.A == org.springframework.context.annotation.AnnotationConfigApplicationContext
// o.s.c.a.C == org.springframework.context.annotation.ConfigurationClassEnhancer

現在開始初始化容器
10:32:18.385 [main] DEBUG o.s.c.a.A - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6842775d
10:32:18.408 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
10:32:18.662 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
10:32:18.665 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'myBeanFactoryPostProcessor'
10:32:18.667 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'configBean'
10:32:18.671 [main] INFO o.s.c.a.C - @Bean method ConfigBean.myBeanFactoryPostProcessor is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
這是BeanFactoryPostProcessor實現類構造器!!
10:32:18.685 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
BeanFactoryPostProcessor調用postProcessBeanFactory方法
10:32:18.687 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
10:32:18.688 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
10:32:18.692 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'myBeanPostProcessor'
這是BeanPostProcessor實現類構造器!!
10:32:18.696 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'myInstantiationAwareBeanPostProcessor'
這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!
10:32:18.702 [main] DEBUG o.s.b.f.s.D - Creating shared instance of singleton bean 'person'
InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法
【構造器】調用Person的構造器實例化
【注入屬性】注入屬性address
【注入屬性】注入屬性name
【注入屬性】注入屬性phone
InstantiationAwareBeanPostProcessor調用postProcessAfterInstantiation方法
InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法
【注入屬性】注入屬性phone // 之所以這裏出現兩次是因爲上面調用了 postProcessPropertyValues 方法
【BeanNameAware接口】調用BeanNameAware.setBeanName()
【BeanFactoryAware接口】調用BeanFactoryAware.setBeanFactory()
BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!
InstantiationAwareBeanPostProcessor調用postProcessBeforeInitialization方法
【InitializingBean接口】調用InitializingBean.afterPropertiesSet()
【init-method】調用<bean>的init-method屬性指定的初始化方法
BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改!
InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法
容器初始化成功
Person [address=廣州, name=張三, phone=110]
現在開始關閉容器!
10:32:18.776 [Thread-0] DEBUG o.s.c.a.A - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6842775d, started on Fri Mar 29 10:32:18 CST 2019
【DiposibleBean接口】調用DiposibleBean.destory()
【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法

 

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