`
jiangxuwen7515
  • 浏览: 7717 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

也谈Spring Bean的生命周期

阅读更多

转自:http://sexycoding.iteye.com/blog/1046775

开篇先用一张老图描述下SpringBean容器的生命周期。

 

插叙一下,记得某个博文中提到:“SpringBean容器只管理非单例Bean的生命周期,单例Bean的生命周期不在管理范围内”,其实我认为这句话恰好说反了。首先明确一点,并非Spring容器中所有的Bean都有生命周期行为,只有接受容器管理生命周期的Bean才具有生命周期行为:而单例(SingletonBean接受容器管理,非单例(non-singletonBean在实例化后,完全交给了客户端代码管理,容器不再跟踪其生命周期,每次客户请求,容器都会创建一个新的实例,所以Spring容易无法知晓Bean何时销毁。

 

继续刚才的话题——Bean容器的生命周期。其实上图有个节点没有画出,就是在实例化所有Bean之前会执行BeanFactoryPostProcessors。不过也不care,因为这和Bean的生命周期没有太大关系,所以没有提及也属正常,权且忽略该节点。

从图中,我们可以看到实例化Bean的过程中有以下几个节点:

1)设置属性值;

2)调用Bean中的BeanNameAware.setBeanName()方法,如果该Bean实现了BeanNameAware接口;

3)调用Bean中的BeanFactoryAware.setBeanFactory()方法,如果该Bean实现了BeanFactoryAware接口;

4)调用BeanPostProcessors.postProcessBeforeInitialization()方法;

5)调用Bean中的afterPropertiesSet方法,如果该Bean实现了InitializingBean接口;

6)调用Bean中的init-method,通常是在配置bean的时候指定了init-method,例如:<bean class="beanClass" init-method="init"></bean>

7)调用BeanPostProcessors.postProcessAfterInitialization()方法;

8)如果该Bean是单例的,则当容器销毁并且该Bean实现了DisposableBean接口的时候,调用destory方法;如果该Beanprototype,则将准备好的Bean提交给调用者,后续不再管理该Bean的生命周期。

 

好了,简单了描述了下那幅图。一切都还太抽象了,作为程序员,代码还是最直接的表达方式。那我们就一起看段演示代码吧。

 

首先,为达到演示效果,我们准备两个待测试的Bean,代码如下:

Java代码  收藏代码
  1. @Component  
  2. public class DemoBean implements BeanFactoryAware, BeanNameAware,  
  3.         InitializingBean, DisposableBean {  
  4.     @PostConstruct  
  5.     public void init() {  
  6.        System.out.println("DemoBean: init-method");  
  7.     }  
  8.     public void destroy() throws Exception {  
  9.        System.out.println("DemoBean: destroy-method!");  
  10.     }  
  11.     public void afterPropertiesSet() throws Exception {  
  12.        System.out.println("DemoBean: after properties set!");  
  13.     }  
  14.     public void setBeanName(String name) {  
  15.        System.out.println("DemoBean: beanName aware, [name=" + name + "]");  
  16.     }  
  17.     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {  
  18.        System.out.println("DemoBean: beanFactory aware, [beanFactory=" + beanFactory.toString() + "]");  
  19.     }  
  20. }  

  

 

Java代码  收藏代码
  1. public class AnotherDemoBean implements InitializingBean {  
  2.    
  3.     @PostConstruct  
  4.     public void postConstruct() {  
  5.        System.out.println("AnotherDemoBean: postConstruct-method");  
  6.     }    
  7.     public void init() {  
  8.        System.out.println("AnotherDemoBean: init-method");  
  9.     }  
  10.     @Override  
  11.     public void afterPropertiesSet() throws Exception {  
  12.        System.out.println("AnotherDemoBean: after properties set!");  
  13.     }  
  14. }  

 

上面两个Bean大致相同,区别在于第一个Bean使用注解方式注入,第二个Bean我们使用配置文件方式,并指定其init-method,用于观察init-methodpostConstruct的执行先后。

 

我们这个演示Bean实现了BeanFactoryAware, BeanNameAware, InitializingBean,  DisposableBean这几个接口,其实这些接口也可理解为Spring容器的一个个扩展点。

 

然后,我们再编写一个BeanPostProcessor,用于演示生命周期中的步骤4和步骤7代码如下:

Java代码  收藏代码
  1. @Component  
  2. public class DemoBeanPostProcessor implements BeanPostProcessor {  
  3.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
  4.        System.out.println("DemoBeanPostProcessor: post process before initialization, [beanName=" + beanName + ", bean=" + bean + "]");  
  5.        return bean;  
  6.     }  
  7.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
  8.        System.out.println("DemoBeanPostProcessor: post process before initialization, [beanName=" + beanName + ", bean=" + bean + "]");  
  9.        return bean;  
  10.     }  
  11. }  

  

最后,我们编写测试类,以及Spring的配置文件,这里我们使用ClassPathXMLApplicationContext加载配置文件和初始化Spring容器。一起看下配置文件和测试类代码:

applicationContext.xml:

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="GBK"?>  
  2.    
  3. <beans xmlns="http://www.springframework.org/schema/beans"  
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
  5.     xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"  
  6.     xsi:schemaLocation="  
  7.         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  8.         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
  9.         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd  
  10.         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
  11.     <context:component-scan base-package="com.shansun.multidemo"></context:component-scan>  
  12.     <bean class="com.shansun.multidemo.spring.lifecycle.AnotherDemoBean" init-method="init"></bean>  
  13. </beans>  

  

Main.java

Java代码  收藏代码
  1. public class Main {  
  2.     @SuppressWarnings("unused")  
  3.     public static void main(String[] args) {  
  4.         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");  
  5.     }  
  6. }  

  

好了,一切就绪,我们就静观程序输出吧:

Java代码  收藏代码
  1. DemoBean: beanName aware, [name=demoBean]  
  2. DemoBean: beanFactory aware, [beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@888e6c:defining beans [demoBean,demoBeanFactoryPostProcessor,demoBeanPostProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,com.shansun.multidemo.spring.lifecycle.AnotherDemoBean#0]; root of factory hierarchy]  
  3. DemoBean: init-method  
  4. DemoBeanPostProcessor: post process before initialization, [beanName=demoBean, bean=com.shansun.multidemo.spring.lifecycle.DemoBean@1deeb40]  
  5. DemoBean: after properties set!  
  6. DemoBeanPostProcessor: post process before initialization, [beanName=demoBean, bean=com.shansun.multidemo.spring.lifecycle.DemoBean@1deeb40]  
  7. AnotherDemoBean: postConstruct-method  
  8. DemoBeanPostProcessor: post process before initialization, [beanName=com.shansun.multidemo.spring.lifecycle.AnotherDemoBean#0, bean=com.shansun.multidemo.spring.lifecycle.AnotherDemoBean@1a7ddcf]  
  9. AnotherDemoBean: after properties set!  
  10. AnotherDemoBean: init-method  
  11. DemoBeanPostProcessor: post process before initialization, [beanName=com.shansun.multidemo.spring.lifecycle.AnotherDemoBean#0, bean=com.shansun.multidemo.spring.lifecycle.AnotherDemoBean@1a7ddcf]  

  

和我们预期的是否一样呢?是的。观察结果发现一个有趣的地方:在配置文件中指定的init-method和使用@PostConstruct注解的方法,孰先孰后呢,两者是否等同呢?后续我将通过分析源码给出结论

 

我们通过演示代码也验证了Bean容器的生命周期,但是还缺点什么吧。对了,透过Spring源码讲述Bean容器的生命周期是否更加直观和令人信服呢?下面我们去Spring源码中一探究竟。这里我们选用的是spring-2.5.6.SEC02

 

大家应该都知道SpringBeanFactoryApplicationContext的关系了吧,ApplicationContext继承自BeanFactory,所以可以操作到bean。更详细的内容可以参考许令波同学的《Spring框架的设计理念与设计模式分析》,里面有较清晰的分析。

 

好了,闲话不多说。

 

首先,我们探视下实例化Bean的方法initializeBean,该方法在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory类下,一起看下该段代码:

Java代码  收藏代码
  1. protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {  
  2.          if (bean instanceof BeanNameAware) {  
  3.                    ((BeanNameAware) bean).setBeanName(beanName);  
  4.          }  
  5.    
  6.          if (bean instanceof BeanClassLoaderAware) {  
  7.                    ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());  
  8.          }  
  9.    
  10.          if (bean instanceof BeanFactoryAware) {  
  11.                    ((BeanFactoryAware) bean).setBeanFactory(this);  
  12.          }  
  13.    
  14.          Object wrappedBean = bean;  
  15.          if (mbd == null || !mbd.isSynthetic()) {  
  16.                    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  
  17.          }  
  18.    
  19.          try {  
  20.                    invokeInitMethods(beanName, wrappedBean, mbd);  
  21.          }  
  22.          catch (Throwable ex) {  
  23.                    throw new BeanCreationException(  
  24.                                      (mbd != null ? mbd.getResourceDescription() : null),  
  25.                                      beanName, "Invocation of init method failed", ex);  
  26.          }  
  27.    
  28.          if (mbd == null || !mbd.isSynthetic()) {  
  29.                    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);  
  30.          }  
  31.          return wrappedBean;  
  32. }  

  

这样够直观了吧,是不是和前文描述的一样呢,J

 

本文源代码下载:https://lb-multi-demo.googlecode.com/svn/trunk/spring-lifecycle-test

分享到:
评论

相关推荐

    spring bean的生命周期

    - **XML配置**:在传统的Spring应用中,Bean的定义通常写在XML配置文件中,如`springbean-xml`中的配置。 - **注解配置**:使用`@Component`,`@Service`,`@Repository`和`@Controller`注解标记类,配合`@...

    Spring bean生命周期demo

    接下来,我们将深入探讨Spring Bean生命周期的各个阶段,并通过具体的示例来演示。 1. **配置阶段** 在Spring容器初始化时,它会读取配置文件(如XML或Java配置),解析Bean定义,包括其依赖关系、初始化方法、...

    Spring Bean生命周期.pdf

    其中,Spring Bean生命周期的管理是Spring框架的核心功能之一,它涉及Spring容器如何创建、配置以及销毁Bean的整个过程。理解Spring Bean的生命周期对于开发高效和可维护的Java应用至关重要。 Spring Bean生命周期...

    谈谈我对Spring Bean 生命周期的理解

    Spring Bean 生命周期是 Spring 框架中的一个核心概念,了解 Spring Bean 的生命周期对我们了解整个 Spring 框架会有很大的帮助。本文将详细介绍 Spring Bean 生命周期的概念、生命周期图、生命周期阶段、生命周期...

    详解Spring中Bean的生命周期和作用域及实现方式

    Spring中Bean的生命周期和作用域及实现方式 Spring是一个非常流行的Java应用程序框架,它提供了一个灵活的机制来管理Bean的生命周期和作用域。Bean的生命周期和作用域是Spring框架中两个非常重要的概念,它们决定了...

    spring bean的生命周期测试代码

    本资源提供了在Spring 4.2环境下关于Bean生命周期的测试代码,帮助我们深入理解这一关键概念。 首先,让我们了解Spring Bean的生命周期主要包含以下几个阶段: 1. **实例化**:Spring容器通过`Class`对象或`...

    SpringBean的生命周期.mdj

    SpringBean的生命周期.mdj

    Spring Bean生命周期&BeanDefinitions1

    Spring框架是Java应用开发中的一个核心组件,尤其在企业级应用中广泛使用。Spring通过其IoC(Inversion of Control,控制反转)容器管理Bean的生命周期,...理解Bean生命周期对于有效管理和优化Spring应用至关重要。

    Spring的bean生命周期

    Bean生命周期的理解对于优化应用性能和理解Spring内部工作原理至关重要。这里我们将深入探讨Spring的Bean生命周期、容器周期以及工厂周期。 首先,让我们从Bean生命周期开始。在Spring中,Bean的生命周期包括以下几...

    Spring Bean 的生命周期

    本篇将详细阐述Spring Bean生命周期的各个阶段,以及如何记忆和深入理解这一过程。 首先,Spring Bean的生命周期可以分为两个主要阶段:容器初始化阶段和容器销毁阶段。 在容器初始化阶段,Spring Bean会经历以下...

    spring bean life cycle

    在Spring框架中,Bean生命周期是核心概念之一,它涉及到Bean的创建、初始化、使用和销毁等阶段。了解和掌握Bean生命周期对于开发高质量的Spring应用至关重要。以下是对Spring Bean生命周期的详细解析。 首先,Bean...

    Spring中Bean的生命周期 applicationcontext的应用(实现国际化,事件的传递)

    在Spring框架中,Bean的生命周期管理和ApplicationContext的应用是两个核心概念,它们对于理解Spring如何管理和协调应用中的对象至关重要。本文将深入探讨这两个主题,并结合国际化(i18n)和事件传递来阐述它们在...

    Spring Bean 生命周期之“我从哪里来?”.docx

    在Spring框架中,Spring Bean的生命周期始于其创建过程,即"我从哪里来?"的问题。首先,要明确几个核心概念:Java Bean、Spring Bean和Spring IoC(控制反转)容器。Java Bean是一种遵循特定规范的Java类,而Spring...

    Spring框架中Bean的生命周期 Spring中Bean有几种作用域

    Spring中的Bean生命周期主要分为两个阶段:容器管理阶段和用户自定义阶段。在容器管理阶段,Spring容器负责Bean的实例化、属性注入、初始化、使用和销毁。而在用户自定义阶段,开发者可以通过定义回调方法或使用特定...

    Spring Bean 的生命周期.docx

    这两个后处理器接口提供了灵活的扩展点,允许开发者在Bean生命周期的关键点进行自定义操作。 ApplicationContext是BeanFactory的升级版,提供了更丰富的功能,包括事件发布、国际化等。在ApplicationContext中,...

    Spring Bean的生命周期详细介绍

    下面以一个简单的Person类为例,展示Spring Bean生命周期的各个阶段: ```java public class Person implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean { // 省略属性和构造器 @...

    SpringBean生命周期详解版

    在Spring框架中,在IOC容器中管理的Bean分为单例和原型两种,单例Bean在容器启动时就实例化,原型Bean则是每次从容器中请求时才会实例化。

    spring bean XML配置入门

    一旦XML配置加载到Spring容器中,容器将根据配置创建Bean实例,并按照定义进行初始化、依赖注入,最后完成Bean的生命周期管理。 10. **实践操作**: 在实际开发中,我们可以使用Eclipse的Spring插件来简化Bean...

    Spring Bean重复执行两次(实例被构造两次)问题分析

    解决这个问题的关键在于深入理解Spring的Bean生命周期和配置机制,检查配置文件、注解使用、依赖关系等,确保每个Bean的定义都是唯一的,且作用域设置正确。同时,对源码进行调试也是一个有效的排查手段,可以追踪到...

Global site tag (gtag.js) - Google Analytics