首页 > 代码库 > Spring总结_06_bean的生命周期

Spring总结_06_bean的生命周期

1.生命周期流程图

上下文ApplicationContext容器中的生命周期:

                 英文图解:

                                    技术分享

                     

                     中文图解:

 

                                       技术分享

Spring Bean的生命周期具体流程:

       1.Bean容器找到配置文件中Spring Bean的定义。
       2.Bean容器利用Java Reflection API创建一个Bean的实例。
       3.如果涉及到一些属性值 利用set方法设置一些属性值。
       4.如果Bean实现了BeanNameAware接口,调用setBeanName()方法,传入Bean的名字。
       5.如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
       6.如果Bean实现了BeanFactoryAware接口,调用setBeanClassLoader()方法,传入ClassLoader对象的实例。
       7.与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。
       8.如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessBeforeInitialization()方法
       9.如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。
       10.如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。
       11.如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行postProcessAfterInitialization()方法
       12.当要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy()方法。
       13.当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。

 

二.各种接口方法分类

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

   1、Bean自身的方法         :这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法

   2、Bean级生命周期接口方法 :这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

   3、容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

   4、工厂后处理器接口方法   :这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的

                                               工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

 

三.接口方法介绍

1. Aware接口   (Bean级

   (1)ApplicationContextAware: 获得ApplicationContext对象,可以用来获取所有Bean definition的名字。

   (2)BeanFactoryAware         : 获得BeanFactory对象,可以用来检测Bean的作用域。

   (3)BeanNameAware           : 获得Bean在配置文件中定义的名字。

   (4)ResourceLoaderAware   : 获得ResourceLoader对象,可以获得classpath中某个文件。

   (5)ServletContextAware    : 在一个MVC应用中可以获取ServletContext对象,可以读取context中的参数。

   (6)ServletConfigAware      : 在一个MVC应用中可以获取ServletConfig对象,可以读取config中的参数。

 

Aware接口是针对某个实现这些接口的Bean定制初始化的过程,几个xxxAware接口的作用类似,暂以 BeanNameAware接口为例:

BeanNameAware接口

此接口用于获得Bean在配置文件中定义的名字:Spring Bean存活于容器之中,一般情况下spring bean对context的情况并不了解,如果希望某个bean知道自己在

                                                                 context中的代号:bean name(一个bean在容器中的id),即可让该bean的类型实现BeanNameAware接口。

示例:

applicationContext.xml

技术分享
<bean id="javaLanguage" class="org.test.spittr.spi.LanguageBean">
    <property name="languageName" value="Java"/>
</bean>
View Code

实体bean

技术分享
package org.test.spittr.spi;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;/

public class LanguageBean implements BeanNameAware {
    private String languageName;
    private String beanName;

    public LanguageBean() {    }

    public String getLanguageName() {
        return languageName;
    }

    public void setLanguageName(String languageName) {
        this.languageName = languageName;
    }

    public void setBeanName(String s) {
        this.beanName = s;
    }

    public String getBeanName() {
        return beanName;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(this.getClass().getName());
        if(this.getBeanName() != null) {
            sb.append(": name \‘").append(this.getBeanName()).append("\‘");
        } else {
            sb.append(": unnamed");
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        Resource resource = new FileSystemResource("/Users/duqi/Downloads/Spittr/src/main/resources/bean-life.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        LanguageBean languageBean = (LanguageBean) beanFactory.getBean("javaLanguage");
        System.out.println(languageBean.getLanguageName());
        System.out.println(languageBean.getBeanName());
        System.out.println(languageBean.toString());
    }
}
View Code

运行结果:

技术分享
Java
javaLanguage
org.test.spittr.spi.LanguageBean: name ‘javaLanguage‘
View Code

 

2. BeanPostProcessor接口(容器级

 (1)如果说上述几个xxxAware接口的作用是定制单个bean的初始化过程,那么BeanPostProcessor接口则可以提供全局的、定制多个bean的初始化过程,只需提供一个实现BeanPostProcessor接口的类即可。

(2)该接口中包含两个方法,postProcessBeforeInitialization和postProcessAfterInitialization。 postProcessBeforeInitialization方法会在容器中的Bean初始化(属性值设置)之前执行, postProcessAfterInitialization方法在容器中的Bean初始化之后执行。

示例:

applicationContext.xml

技术分享
<bean class="com.giraffe.spring.service.CustomerBeanPostProcessor"/>
View Code

实体类

技术分享
public class CustomerBeanPostProcessor implements BeanPostProcessor {
 
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行BeanPostProcessor的postProcessBeforeInitialization方法,beanName=" + beanName);
        return bean;
    }
 
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行BeanPostProcessor的postProcessAfterInitialization方法,beanName=" + beanName);
        return bean;
    }
 
}
View Code

 

3. InitializingBean接口   和   DisposableBean接口Bean级

       这两个接口都只包含一个方法。通过实现InitializingBean接口的afterPropertiesSet()方法可以在Bean属性值设置好之后做一些操作,实现DisposableBean接口的destroy()方法可以在销毁Bean之前做一些操作。

      在bean的声明周期中,afterPropertiesSet()方法的调用介于postProcessBeforeInitialization()方法和postProcessAfterInitialization()方法之间。

在实际项目中,可以考虑按照如下模式使用InitializingBean接口:

技术分享
public class GiraffeService implements InitializingBean,DisposableBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("执行InitializingBean接口的afterPropertiesSet方法");
 
    }
 
    @Override
    public void destroy() throws Exception {
        System.out.println("执行DisposableBean接口的destroy方法");
    }
}
View Code

       这种方法比较简单,但是不建议使用。因为这样会将Bean的实现和Spring框架耦合在一起。

 

Spring总结_06_bean的生命周期