Spring Bean的生命周期

来源:互联网 发布:linux iso 写入u盘 编辑:程序博客网 时间:2024/05/17 03:42

  • 原文地址:http://www.cnblogs.com/zrtqsk/p/3735273.html

Spring作为当前Java最流行、最强大的轻量级框架,受到了程序员的热烈欢迎。准确的了解Spring Bean的生命周期是非常必要的。我们通常使用ApplicationContext作为Spring容器。这里,我们讲的也是 ApplicationContext中Bean的生命周期。而实际上BeanFactory也是差不多的,只不过处理器需要手动注册。

 转载请注明地址 http://www.cnblogs.com/zrtqsk/p/3735273.html,谢谢。

一、生命周期流程图:

  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等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

  

三、演示

我们用一个简单的Spring Bean来演示一下Spring Bean的生命周期。

1、首先是一个简单的Spring Bean,调用Bean自身的方法和Bean级生命周期接口方法,为了方便演示,它实现了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口,同时有2个方法,对应配置文件中<bean>的init-method和destroy-method。如下:

 

复制代码
 1 package springBeanTest; 2  3 import org.springframework.beans.BeansException; 4 import org.springframework.beans.factory.BeanFactory; 5 import org.springframework.beans.factory.BeanFactoryAware; 6 import org.springframework.beans.factory.BeanNameAware; 7 import org.springframework.beans.factory.DisposableBean; 8 import org.springframework.beans.factory.InitializingBean; 9 10 /**11  * @author qsk12  */13 public class Person implements BeanFactoryAware, BeanNameAware,14         InitializingBean, DisposableBean {15 16     private String name;17     private String address;18     private int phone;19 20     private BeanFactory beanFactory;21     private String beanName;22 23     public Person() {24         System.out.println("【构造器】调用Person的构造器实例化");25     }26 27     public String getName() {28         return name;29     }30 31     public void setName(String name) {32         System.out.println("【注入属性】注入属性name");33         this.name = name;34     }35 36     public String getAddress() {37         return address;38     }39 40     public void setAddress(String address) {41         System.out.println("【注入属性】注入属性address");42         this.address = address;43     }44 45     public int getPhone() {46         return phone;47     }48 49     public void setPhone(int phone) {50         System.out.println("【注入属性】注入属性phone");51         this.phone = phone;52     }53 54     @Override55     public String toString() {56         return "Person [address=" + address + ", name=" + name + ", phone="57                 + phone + "]";58     }59 60     // 这是BeanFactoryAware接口方法61     @Override62     public void setBeanFactory(BeanFactory arg0) throws BeansException {63         System.out64                 .println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");65         this.beanFactory = arg0;66     }67 68     // 这是BeanNameAware接口方法69     @Override70     public void setBeanName(String arg0) {71         System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");72         this.beanName = arg0;73     }74 75     // 这是InitializingBean接口方法76     @Override77     public void afterPropertiesSet() throws Exception {78         System.out79                 .println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");80     }81 82     // 这是DiposibleBean接口方法83     @Override84     public void destroy() throws Exception {85         System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");86     }87 88     // 通过<bean>的init-method属性指定的初始化方法89     public void myInit() {90         System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");91     }92 93     // 通过<bean>的destroy-method属性指定的初始化方法94     public void myDestory() {95         System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");96     }97 }
复制代码

 

2、接下来是演示BeanPostProcessor接口的方法,如下:

复制代码
 1 package springBeanTest; 2  3 import org.springframework.beans.BeansException; 4 import org.springframework.beans.factory.config.BeanPostProcessor; 5  6 public class MyBeanPostProcessor implements BeanPostProcessor { 7  8     public MyBeanPostProcessor() { 9         super();10         System.out.println("这是BeanPostProcessor实现类构造器!!");11         // TODO Auto-generated constructor stub12     }13 14     @Override15     public Object postProcessAfterInitialization(Object arg0, String arg1)16             throws BeansException {17         System.out18         .println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!");19         return arg0;20     }21 22     @Override23     public Object postProcessBeforeInitialization(Object arg0, String arg1)24             throws BeansException {25         System.out26         .println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!");27         return arg0;28     }29 }
复制代码

如上,BeanPostProcessor接口包括2个方法postProcessAfterInitializationpostProcessBeforeInitialization,这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。返回值也都是要处理的Bean对象。这里要注意。

 

3、InstantiationAwareBeanPostProcessor 接口本质是BeanPostProcessor的子接口,一般我们继承Spring为其提供的适配器类InstantiationAwareBeanPostProcessor Adapter来使用它,如下:

复制代码
 1 package springBeanTest; 2  3 import java.beans.PropertyDescriptor; 4  5 import org.springframework.beans.BeansException; 6 import org.springframework.beans.PropertyValues; 7 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; 8  9 public class MyInstantiationAwareBeanPostProcessor extends10         InstantiationAwareBeanPostProcessorAdapter {11 12     public MyInstantiationAwareBeanPostProcessor() {13         super();14         System.out15                 .println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");16     }17 18     // 接口方法、实例化Bean之前调用19     @Override20     public Object postProcessBeforeInstantiation(Class beanClass,21             String beanName) throws BeansException {22         System.out23                 .println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");24         return null;25     }26 27     // 接口方法、实例化Bean之后调用28     @Override29     public Object postProcessAfterInitialization(Object bean, String beanName)30             throws BeansException {31         System.out32                 .println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");33         return bean;34     }35 36     // 接口方法、设置某个属性时调用37     @Override38     public PropertyValues postProcessPropertyValues(PropertyValues pvs,39             PropertyDescriptor[] pds, Object bean, String beanName)40             throws BeansException {41         System.out42                 .println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");43         return pvs;44     }45 }
复制代码

这个有3个方法,其中第二个方法postProcessAfterInitialization就是重写了BeanPostProcessor的方法。第三个方法postProcessPropertyValues用来操作属性,返回值也应该是PropertyValues对象。

 

4、演示工厂后处理器接口方法,如下:

复制代码
 1 package springBeanTest; 2  3 import org.springframework.beans.BeansException; 4 import org.springframework.beans.factory.config.BeanDefinition; 5 import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 6 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 7  8 public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { 9 10     public MyBeanFactoryPostProcessor() {11         super();12         System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");13     }14 15     @Override16     public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)17             throws BeansException {18         System.out19                 .println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");20         BeanDefinition bd = arg0.getBeanDefinition("person");21         bd.getPropertyValues().addPropertyValue("phone", "110");22     }23 24 }
复制代码

 

5、配置文件如下beans.xml,很简单,使用ApplicationContext,处理器不用手动注册:

复制代码
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"    xsi:schemaLocation="            http://www.springframework.org/schema/beans             http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">    <bean id="beanPostProcessor" class="springBeanTest.MyBeanPostProcessor">    </bean>    <bean id="instantiationAwareBeanPostProcessor" class="springBeanTest.MyInstantiationAwareBeanPostProcessor">    </bean>    <bean id="beanFactoryPostProcessor" class="springBeanTest.MyBeanFactoryPostProcessor">    </bean>        <bean id="person" class="springBeanTest.Person" init-method="myInit"        destroy-method="myDestory" scope="singleton" p:name="张三" p:address="广州"        p:phone="15900000000" /></beans>
复制代码

 

 

6、下面测试一下:

复制代码
 1 package springBeanTest; 2  3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5  6 public class BeanLifeCycle { 7  8     public static void main(String[] args) { 9 10         System.out.println("现在开始初始化容器");11         12         ApplicationContext factory = new ClassPathXmlApplicationContext("springBeanTest/beans.xml");13         System.out.println("容器初始化成功");    14         //得到Preson,并使用15         Person person = factory.getBean("person",Person.class);16         System.out.println(person);17         18         System.out.println("现在开始关闭容器!");19         ((ClassPathXmlApplicationContext)factory).registerShutdownHook();20     }21 }
复制代码

关闭容器使用的是实际是AbstractApplicationContext的钩子方法。

我们来看一下结果:

复制代码
现在开始初始化容器2014-5-18 15:46:20 org.springframework.context.support.AbstractApplicationContext prepareRefresh信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@19a0c7c: startup date [Sun May 18 15:46:20 CST 2014]; root of context hierarchy2014-5-18 15:46:20 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions信息: Loading XML bean definitions from class path resource [springBeanTest/beans.xml]这是BeanFactoryPostProcessor实现类构造器!!BeanFactoryPostProcessor调用postProcessBeanFactory方法这是BeanPostProcessor实现类构造器!!这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!2014-5-18 15:46:20 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@9934d4: defining beans [beanPostProcessor,instantiationAwareBeanPostProcessor,beanFactoryPostProcessor,person]; root of factory hierarchyInstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法【构造器】调用Person的构造器实例化InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法【注入属性】注入属性address【注入属性】注入属性name【注入属性】注入属性phone【BeanNameAware接口】调用BeanNameAware.setBeanName()【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!【InitializingBean接口】调用InitializingBean.afterPropertiesSet()【init-method】调用<bean>的init-method属性指定的初始化方法BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法容器初始化成功Person [address=广州, name=张三, phone=110]现在开始关闭容器!【DiposibleBean接口】调用DiposibleBean.destory()【destroy-method】调用<bean>的destroy-method属性指定的初始化方法

  • 原文地址:http://997004049-qq-com.iteye.com/blog/1729793

Spring Bean 生命周期

任何一个事物都有自己的生命周期,生命的开始、生命中、生命结束。大家最熟悉的应该是servlet 的生命周期吧。和 servlet 一样 spring bean 也有自己的生命周期。本文我就向大家讲述 spring bean 的生命周期,这个对理解 spring 框架有非常好的作用。

大家应该知道spring 中有几种供 springbean 生存的容器: BeanFactory 、 ApplicationContext 、webApplicationContext 。由于 ApplicationContext 和 webApplicationContext 基本一样。所有这里就只介绍BeanFactory 和 ApplicationContext 。

理解springBean 的生命周期主要通过两个层面来理解。其一是 Bean 的作用范围,其一是实例化 Bean 时所经历的一系列阶段。

一、 BeanFactory

下图描述了BeanFactory 中 bean 生命周期的完整过程

 

 

1. 当调用者通过 getBean( name )向 容器寻找Bean 时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在实例 bean 之前,将调用该接口的 postProcessBeforeInstantiation ()方法,

2. 根据配置情况调用 Bean构造函数或工厂方法实例化 bean  

 

3. 如果容器注册了 org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在实例 bean 之后,调用该接口的 postProcessAfterInstantiation ()方法,可以在这里对已经实例化的对象进行一些装饰。

4. 受用依赖注入,Spring 按照 Bean 定义信息配置 Bean 的所有属性 ,在设置每个属性之前将调用InstantiationAwareBeanPostProcess接口的 postProcessPropertyValues ()方法 。 

 

5 .如果 Bean 实现了 BeanNameAware 接口,工厂调用 Bean 的 setBeanName() 方法传递 Bean 的 ID 。 

 

6 .如果 Bean 实现了 BeanFactoryAware 接口,工厂调用 setBeanFactory() 方法传入工厂自身。 

 

7 .如果 BeanPostProcessor 和 Bean 关联,那么 将调用该接口 postProcessBeforeInitialzation() 方法  bean进行加工操作,这个非常重要, spring 的 AOP 就是用它实现的。  

 

8. 如果bean 实现了 InitializingBean 接口,将调用 afterPropertiesSet ()方法

 

9 如果Bean 指定了 init-method 方法,它将被调用。 

 

10 如果有BeanPsotProcessor 和 Bean 关联,那么它们的 postProcessAfterInitialization() 方法将被调用。 到这个时候, Bean 已经可以被应用系统使用了  

 

11. 如果在<bean> 中指定了该 bean 的作用范围为 scope="prototype", 将 bean 的调用者,调用者管理该 bean 的生命周期, spring 不在管理该 bean 。

 

12. 如果在<bean> 中指定了该 bean 的作用范围为 scope="singleton", 则将该 bean 放入 springIOC 的缓存池中,将触发 spring 对该 bean 的生命周期管理。

 

13. 有两种方法可以把它从Bean Factory 中删除掉   

1.如果 Bean 实现了 DisposableBean 接口, destory() 方法被调用。 

 

2.如果指定了订制的销毁方法,就调用这个方法。 

 

 

 

总结:

Bean的完整生命周期从 spring 容器开始实例化 bean 开始,到销毁。可以从三点来理解

1、 bean自身的方法:包括构造方法、 set 方法、 init-method 指定的方法、 destroy-method 指定的方法

2、 Bean级生命周期接口方法:如 BeanNameAware  BeanFactoryAware 等这些接口方法由 bean类实现。

3、 容器级生命周期接口方法:上图中带星的。有InstantiationAwareBeanPostProcessor 、 BeanPostProcessor 等。一般称为后处理 器。他们一般不由bean 本身实现,独立存在,注册到 spring 容器中。 Spring 通过接口反射预先知道,当 spring 容器创建任何 bean 时,这些后处理器都会发生作用。所以他们是全局的,用户可以通过编码对只感兴趣的 bean 进行处理。

 

 

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

 

 

二、 ApplicationContext

下图描述了ApplicationContext 的生命周期

 

 

通过上图很容易发现其实应该上下文和BeanFactory 只是多了一个接口, 如果Bean 实现了ApplicationContextAwre 接口, setApplicationContext() 方法被调用。

还有如果配置文件中生明了工厂后处理器接口 BeanFactoryPostProcessor的实现类,则应用上下文在装配配置文件之后初始化 bean 之前将调用该接口对配置信息进行加工。

还有应该上下文的这些后处理器只要和普通的bean 一样配置在 spring 配置文件中就行了,不需要事先声明。

 

三、 总结  

 

Spring为 bean 提供了细致周全的生命周期过程,通过实现特定的接口或通过《bean 》属性设置,都可以对 bean 的生命周期过程施加影响。我们可以随意的配置bean 的属性,使用非常灵活。但笔者在这里建议大家不要过多的使用 bean 实现接口,因为这样会使你的代码和 spring 聚合比较紧密。可以考虑使用后处理 bean ,来实现一些特殊的功能,并且非常的方便。

0 0
原创粉丝点击