- 浏览: 295570 次
- 性别:
- 来自: 安徽
文章分类
最新评论
-
fanjf:
因为不是太懂,所以摘录!
DataStage---向目的库插入时出现问题:MLOG$ -
fanjf:
oracle 位图索引:位图索引: 解决某一表数据很多,但某一 ...
【转】 mysql 添加列,修改列,删除列。 -
fanjf:
创建索引:CREATE TABLE mm (m1 CHAR(1 ...
【转】 mysql 添加列,修改列,删除列。 -
fanjf:
查询mysql 的表emp 的约束:
SELECT * FR ...
【转】 mysql 添加列,修改列,删除列。 -
fanjf:
为什么 update 不报错,结果为空?
关于MYSQL 检查check约束
也谈Spring Bean的生命周期
- 博客分类:
- Spring
开篇先用一张老图描述下 Spring 中 Bean 容器的生命周期。
插叙一下,记得某个博文中提到:“ Spring 的 Bean 容器只管理非单例 Bean 的生命周期,单例 Bean 的生命周期不在管理范围内”,其实我认为这句话恰好说反了。首先明确一点,并非 Spring 容器中所有的 Bean 都有生命周期行为,只有接受容器管理生命周期的 Bean 才具有生命周期行为:而单例( Singleton ) Bean 接受容器管理,非单例( non-singleton ) Bean 在实例化后,完全交给了客户端代码管理,容器不再跟踪其生命周期,每次客户请求,容器都会创建一个新的实例,所以 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. postProcess After Initialization () 方法;
8)如果该 Bean 是单例的,则当容器销毁并且该 Bean 实现了 DisposableBean 接口的时候,调用 destory 方法;如果该 Bean 是 prototype ,则将准备好的 Bean 提交给调用者,后续不再管理该 Bean 的生命周期。
好了,简单了描述了下那幅图。一切都还太抽象了,作为程序员,代码还是最直接的表达方式。那我们就一起看段演示代码吧。
首先,为达到演示效果,我们准备两个待测试的 Bean ,代码如下:
- @Component
- public class DemoBean implements BeanFactoryAware, BeanNameAware,
- InitializingBean, DisposableBean {
- @PostConstruct
- public void init() {
- System.out.println( "DemoBean: init-method" );
- }
- public void destroy() throws Exception {
- System.out.println( "DemoBean: destroy-method!" );
- }
- public void afterPropertiesSet() throws Exception {
- System.out.println( "DemoBean: after properties set!" );
- }
- public void setBeanName(String name) {
- System.out.println( "DemoBean: beanName aware, [name=" + name + "]" );
- }
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- System.out.println( "DemoBean: beanFactory aware, [beanFactory=" + beanFactory.toString() + "]" );
- }
- }
- public class AnotherDemoBean implements InitializingBean {
- @PostConstruct
- public void postConstruct() {
- System.out.println( "AnotherDemoBean: postConstruct-method" );
- }
- public void init() {
- System.out.println( "AnotherDemoBean: init-method" );
- }
- @Override
- public void afterPropertiesSet() throws Exception {
- System.out.println( "AnotherDemoBean: after properties set!" );
- }
- }
上面两个 Bean 大致相同,区别在于第一个 Bean 使用注解方式注入,第二个 Bean 我们使用配置文件方式,并指定其 init-method ,用于观察 init-method 与 postConstruct 的执行先后。
我们这个演示 Bean 实现了 BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean 这几个接口,其实这些接口也可理解为 Spring 容器的一个个扩展点。
然后,我们再编写一个 BeanPostProcessor ,用于演示生命周期中的步骤 4 和步骤 7 。 代码如下:
- @Component
- public class DemoBeanPostProcessor implements BeanPostProcessor {
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- System.out.println( "DemoBeanPostProcessor: post process before initialization, [beanName=" + beanName + ", bean=" + bean + "]" );
- return bean;
- }
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- System.out.println( "DemoBeanPostProcessor: post process before initialization, [beanName=" + beanName + ", bean=" + bean + "]" );
- return bean;
- }
- }
最后,我们编写测试类,以及 Spring 的配置文件,这里我们使用 ClassPathXMLApplicationContext 加载配置文件和初始化 Spring 容器。一起看下配置文件和测试类代码:
applicationContext.xml:
- <? xml version = "1.0" encoding = "GBK" ?>
- < beans xmlns = "http://www.springframework.org/schema/beans"
- xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:aop = "http://www.springframework.org/schema/aop"
- xmlns:context = "http://www.springframework.org/schema/context" xmlns:tx = "http://www.springframework.org/schema/tx"
- xsi:schemaLocation ="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd" >
- < context:component-scan base-package = "com.shansun.multidemo" > </ context:component-scan >
- < bean class = "com.shansun.multidemo.spring.lifecycle.AnotherDemoBean" init-method = "init" > </ bean >
- </ beans >
Main.java
- public class Main {
- @SuppressWarnings ( "unused" )
- public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext( "applicationContext.xml" );
- }
- }
好了,一切就绪,我们就静观程序输出吧:
- DemoBean: beanName aware, [name=demoBean]
- 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]
- DemoBean: init-method
- DemoBeanPostProcessor: post process before initialization, [beanName=demoBean, bean=com.shansun.multidemo.spring.lifecycle.DemoBean @1deeb40 ]
- DemoBean: after properties set!
- DemoBeanPostProcessor: post process before initialization, [beanName=demoBean, bean=com.shansun.multidemo.spring.lifecycle.DemoBean @1deeb40 ]
- AnotherDemoBean: postConstruct-method
- DemoBeanPostProcessor: post process before initialization, [beanName=com.shansun.multidemo.spring.lifecycle.AnotherDemoBean# 0 , bean=com.shansun.multidemo.spring.lifecycle.AnotherDemoBean @1a7ddcf ]
- AnotherDemoBean: after properties set!
- AnotherDemoBean: init-method
- 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 。
大家应该都知道 Spring 中 BeanFactory 和 ApplicationContext 的关系了吧, ApplicationContext 继承自 BeanFactory ,所以可以操作到 bean 。更详细的内容可以参考许令波同学的《 Spring 框架的设计理念与设计模式分析》,里面有较清晰的分析。
好了,闲话不多说。
首先,我们探视下实例化 Bean 的方法 initializeBean ,该方法在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory 类下,一起看下该段代码:
- protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
- if (bean instanceof BeanNameAware) {
- ((BeanNameAware) bean).setBeanName(beanName);
- }
- if (bean instanceof BeanClassLoaderAware) {
- ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
- }
- if (bean instanceof BeanFactoryAware) {
- ((BeanFactoryAware) bean).setBeanFactory( this );
- }
- Object wrappedBean = bean;
- if (mbd == null || !mbd.isSynthetic()) {
- wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
- }
- try {
- invokeInitMethods(beanName, wrappedBean, mbd);
- }
- catch (Throwable ex) {
- throw new BeanCreationException(
- (mbd != null ? mbd.getResourceDescription() : null ),
- beanName, "Invocation of init method failed" , ex);
- }
- if (mbd == null || !mbd.isSynthetic()) {
- wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
- }
- return wrappedBean;
- }
这样够直观了吧,是不是和前文描述的一样呢, J
本文源代码下载: https://lb-multi-demo.googlecode.com/svn/trunk/spring-lifecycle-test
发表评论
-
org.springframework.dao.DataAccessResourceFailureException Io 异常: tConnection re
2014-02-14 11:05 2302最近程序老是出现等待一会后 操作程序页面 出现下面异常 ... -
MyBatis3整合Spring3的Transaction事务处理
2012-03-19 10:48 926正如第二版,Spring 仅支持 iBatis2。那么我们就想 ... -
MyBatis3整合Spring3、SpringMVC3
2012-03-19 10:47 1081开发环境: System:Windows ... -
FreeMarker配置详解
2012-03-16 16:52 2110<? xml version="1.0&qu ... -
FreeMarker整合Spring 3.0
2012-03-16 16:39 909开发环境: System:Windows We ... -
Spring 的AOP(面向切面编程)
2012-03-05 17:59 946AOP 是一门编程技术, spring 的 ... -
spring 配置完Service怎么得到Action
2012-02-29 16:36 1288写一个手机发送短信的后台处理在包装短信时,今天遇到一个问题: ... -
Spring的优点:
2012-02-21 19:28 759Spring带给我们什么: ◆方便解耦,简化开发 ... -
Spring中两种注入方式的对比
2012-02-21 19:26 1233spring依赖注入的两种方式: 1.设置注入; 2.构造 ... -
spring中bean继承与java继承的区别
2012-02-21 19:25 8291.Spring中子bean和父bean可以是不同类型,jav ... -
spring依赖关系配置
2012-02-21 19:25 993依赖注入--如果A依赖于B,则B实例不再由A负责生成,而有容器 ... -
Spring 依赖检查
2012-02-21 19:24 869在进行说明bean依赖检查的几种模式前,先给大家说明我们为什么 ... -
Spring内核研究-管理bean的声明周期一(InitializingBean和init-method)
2012-02-20 10:01 1024... -
源码解析:init-method、@PostConstruct、afterPropertiesSet孰先孰后
2012-02-15 17:25 1502Spring 容器中的 Bean ... -
Spring的InitializingBean和init-method
2012-02-15 17:24 887Spring在设置完一个bean所有的属性后,会检查bean是 ... -
Spring的init-method 与afterPropertiesSet
2012-02-15 17:22 1344init-method 与afterPropertiesSet ... -
Spring事务配置的五种方式
2012-02-15 16:55 677前段时间对Spring的事务配置做了比较深入的研究,在此之间对 ...
相关推荐
spring bean 的生命周期,把运行结果的日志,用sublime打开对比查看,你会有比较清晰的认识
Spring bean生命周期demo
Springbean生命周期
SpringBean的生命周期.mdj
此资源是我的博客bean的生命周期的测试代码,只有源代码,没有相关库文件,环境是spring4.2 ,
Spring Bean 的生命周期在整个 Spring 中占有很重要的位置,掌握这些可以加深对 Spring 的理解。这篇文章主要介绍了Spring Bean 生命周期,需要的朋友可以参考下
本篇文章主要介绍了浅谈Spring bean 生命周期验证,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Spring Bean 生命周期之“我从哪里来?”
这个工程主要实现了: Spring中Bean的生命周期 applicationcontext的应用(实现国际化,事件的传递)
介绍了Spring的Bean周期,容器周期,工厂周期,运行代码后可以看到运行结果
四份资料介绍Spring Bean 的生命周期,从认识,熟悉,深究,记忆Spring Bean。希望这份资料能帮助你!
虽然可以随意配置 <bean> 的属性,但是建议不要过多地使 Bean 实现接,因为这样会导致代码和 Spring 的聚合过于紧密第 1 步:实例化Bean第
主要给大家介绍了Spring中Bean的生命周期和作用域及实现方式的相关资料,文中介绍的非常详细,对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。
Spring的生命周期是指实例化Bean时所经历的一系列阶段,即通过getBean()获取bean对象及设置对象属性时,Spring框架做了哪些事。Bean的生命周期从Spring容器实例化Bean到销毁Bean。 本文分别对 BeanFactory 和 ...
主要介绍了Spring Bean的生命周期的相关资料,需要的朋友可以参考下
学习Spring过程中,使用Eclipse调试Spring源码的关键断点文件。
Spring管理的Bean的生命周期
一般情况下,我们只是关心如何正确地将Bean装配到容器中,并不关心Ioc容器是如何装配和销毁Bean的过程。但是恰恰有时候,我们需要自定义初始化或销毁Bean的过程,以满足一些“特殊的”需求。比如,数据源在关闭的...
主要介绍了Spring bean生命周期配置过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下