`
dylan0514sina.cn
  • 浏览: 92337 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

bean的创建周期回调

 
阅读更多
初始化回调
    实现org.springframework.beans.factory.InitializingBean接口,afterPropertiesSet方法将在bean的所有属性装配好之后调用

  
<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>

public class AnotherExampleBean implements InitializingBean {

  public void afterPropertiesSet() {
      // do some initialization work
  }
}

    自定义初始化方法,指定init-method  
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>

public class ExampleBean {

  public void init() {
      // do some initialization work
  }
}

析构回调
   只针对scope=单例,对于prototype的bean没有以下销毁方法,但对于其他的Scope指定的Bean,由scope对象的registerDestructionCallback注册回调
   实现org.springframework.beans.factory.DisposableBean接口,destroy将在容器销毁时调用
  <bean id="exampleInitBean" class="examples.AnotherExampleBean"/>

public class AnotherExampleBean implements DisposableBean {

  public void destroy() {
      // do some destruction work (like releasing pooled connections)
  }
}

  自定义销毁方法,指定destroy-method
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
public class ExampleBean {

  public void cleanup() {
      // do some destruction work (like releasing pooled connections)
  }
}

析构回调只对单例scope=singleton有效。以上几个方法的调用顺序为
  •   afterPropertiesSet()
  •   自定义init()
  •   destroy()
  •   自定义destroy()
容器刷新和关闭回调
Lifecycle接口为有自己生命周期的(比如管理一组线程)组件对象提供了必要的方法,Phased接口定义了组件执行的先后顺序,返回值越小,开始执行的越早,结束执行的越晚
SmartLifecycle接口除了继承以上两个接口的特点,还定义了两个方法isAutoStartup和
stop(Runnable callback)。
   容器初始化时,会触发所有的Lifecycle对象的start方法。对于SmartLifecycle对象,而且会在容器的refresh事件触发时调用start,只要isAutoStartup返回true。
stop(Runnable)支持异步式关闭操作。
public interface Lifecycle {

  void start();

  void stop();

  boolean isRunning();

}
public interface Phased {

  int getPhase();

}


public interface SmartLifecycle extends Lifecycle, Phased {

  boolean isAutoStartup();

  void stop(Runnable callback);

}

lifecycle处理流程



  1. LifecycleProcessor在容器初始化或refresh事情触发,或者作
  2.    为其他 LifecycleProcessor调度对象时执行start调度,结束时执行stop调度
  3. 所有lifecycle对象的phrase值=0,和smartLifecycle对象一起被调度;
  4. 所有phrase值相同的lifecycle或其子对象被放置到一个组中,这样组之间通过phrase
  5.    由小到大排序先后被调度
  6. 最终,发现lifecycle之间的依赖关系,存在管理A->B,B实例作为A的属性,B作
  7.   为lifecyle 对象被调度之前,先检查A,如果A也为lifecyle且没有被调度过,则
       先被 调度;这样直到依赖B的所有lifecycle对象调度完,才执行B的调度
  8. 组内的所有成员执行完STOP之前,主线程会一直诸塞,除非
  9. 指定的timeoutPerShutdownPhase时间到,使用JDK CountDownLatch实现。这种
    机制就好比上课铃响了,如果班级的学生没有到齐,那在教室的所有学生必须等待!
      ---一个也不能少;或者加班时把任务分成N份给每个人,先完成的必须等待当所有人
    任务结束之后才能聚餐!不过我们可以指定最长等待时间正如timeoutPerShutdownPhase
  10. timeoutPerShutdownPhase默认为30s,可需重新指定或者使用自定义lifecycleProcessor,bean的标识一定是"lifecycleProcessor"配置如下
<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
  <!-- timeout value in milliseconds -->
  <property name="timeoutPerShutdownPhase" value="10000"/>
</bean>

在非web环境下优雅的关闭IOC容器
   在web环境下,IOC容器在装载时已经注入了“钩子”,这些“钩子”是一些线程。当JVM关闭时,这些“钩子”会开始运行,这里我们可以调用单例对象的销毁方法,当然必须正确定义这些销毁方法
在非WEB环境下如测试环境中,必须手动调用registerShutdownHook()注册"钩子".
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public final class Boot {

  public static void main(final String[] args) throws Exception {
      AbstractApplicationContext ctx
          = new ClassPathXmlApplicationContext(new String []{"beans.xml"});

      // add a shutdown hook for the above context... 
      ctx.registerShutdownHook();

      // app runs here...

      // main method exits, hook is called prior to the app shutting down...
  }
}

“钩子”的注册落实到runtime.addShutdownHook(Thread thread).
  JDK解释
   关闭钩子 只是一个已初始化但尚未启动的线程。虚拟机开始启用其关闭序列时,它会以某种未指定的顺序启动所有已注册的关闭钩子,并让它们同时运行。运行完所有的钩子后,如果已启用退出终结,那么虚拟机接着会运行所有未调用的终结方法。最后,虚拟机会暂停。注意,关闭序列期间会继续运行守护线程,如果通过调用 exit 方法来发起关闭序列,那么也会继续运行非守护线程。
     启动钩子调用->如果设置runFinalizersOnExit(true)启用退出时终结,则强制调用所有对象的仍未调用的finalize()方法(此方法在对象不可用时调用,强制性调用可能会对没有回收的对象即被其他对象引用,调用将是不安全的)

   
package com.tmmh.th;

public class Main {

	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		Runtime.runFinalizersOnExit(true);
		Man man = new Man();
	//	man = null;
		Runtime.getRuntime().addShutdownHook(new Thread(){

			@Override
			public void run() {
				System.out.println("hook call");
			}
			
		});
		//System.gc();
		//Runtime.getRuntime().runFinalization();
	}

}

package com.tmmh.th;

public class Man {

	@Override
	protected void finalize() throws Throwable {
		// TODO Auto-generated method stub
	  System.out.println("finalize call");
	}
	
	
}

hook call
finalize call

    halt方法调用将强行终止JVM,钩子和对象的finalize()从不被调用,即使已经在运行中,也会终止。
     一旦开始了关闭序列,则不可能注册新的关闭钩子或取消注册先前已注册的钩子。尝试执行这些操作会导致抛出 IllegalStateException。
     关闭钩子可在虚拟机生命周期中的特定时间运行,因此应保护性地对其进行编码。特别是应将关闭钩子编写为线程安全的,并尽可能地避免死锁。关闭钩子还应该不盲目地依靠某些服务,这些服务可能已注册了自己的关闭钩子,所以其本身可能正处于关闭进程中。例如,试图使用其他基于线程的服务(如 AWT 事件指派线程)可能导致死锁。
     关闭钩子应该快速地完成其工作。当程序调用 exit 时,虚拟机应该迅速地关闭并退出。由于用户注销或系统关闭而终止虚拟机时,底层的操作系统可能只允许在固定的时间内关闭并退出。因此在关闭钩子中尝试进行任何用户交互或执行长时间的计算都是不明智的。
    与其他所有线程一样,通过调用线程 ThreadGroup 对象的 uncaughtException 方法, 可在关闭钩子中处理未捕获的异常。此方法的默认实现是将该异常的堆栈跟踪打印至 System.err 并终止线程;它不会导致虚拟机退出或暂停

Aware接口
当ApplicationContext创建实现org.springframework.context.ApplicationContextAware接口的对象时,这个对象被提供ApplicationContext的引用,通过可以进行硬编码与容器交互。注入的时机在装配属性之后,afterPropertiesSet 之前。

bean创建时的顺序
  1. postProcessBeforeInstantiation返回可能的代理对象如自动代理,如果有,则调用postProcessAfterInitialization方法,创建结束。
  2. 通过实例化策略:工厂方法、构造装配、简单实例化创建对象
  3. postProcessMergedBeanDefinition通过元数据信息注入到beanDefinition
  4. 添加防止循环依赖的ObjectFactory
  5. postProcessAfterInstantiation返回false,则停止装配属性
  6. postProcessPropertyValues修改属性值,返回null则停止装配属性
  7. 根据依赖策略检查要设置的属性,抛出依赖检查异常终止bean获取装配属性
  8. 依次调用BeanNameAware、BeanClassLoaderAware、BeanFactoryAware设置方法
  9. postProcessBeforeInitialization方法,例如ApplicationContextAwareProcessor中调用EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware设置方法
  10. afterPropertiesSet
  11. 自定义init-method
  12. postProcessAfterInitialization,比如自动代理
  13. 循环依赖检查:如果防止循环依赖的ObjectFactory已经创建,说明确实有过循环依赖。如果初始化后的bean和之前指定的是同一对象,则返回防止循环依赖的ObjectFactory已经创建的bean;如果不是同一对象,比如初始化时创建了代理;对于这种情况作如下检查
  14.     allowRawInjectionDespiteWrapping为false(默认为false)
       有依赖bean的对象,且这些对象时不作为类型检查时而创建的对象
    以上两种情况都存在,则抛出循环依赖异常
  15. 对于单例对象,注册DisposableBean;对于自定义scope对象,通过scope.registerDestructionCallback注册DisposableBean
  • 大小: 91 KB
分享到:
评论

相关推荐

    开源框架面试专题及答案.pdf

    &gt; Spring bean factory 负责管理在 spring 容器中被创建的 bean 的生命周期。Bean 的生命 周期由两组回调(call back)方法组成。 &gt; 初始化之后调用的回调方法。 &gt; 销毁之前调用的回调方法。 &gt; Spring 框架提供了...

    spring的详细介绍

    Spring介绍 1. Spring 2. 使用spring的主要目的 3. Spring的模块 Ejb容器(以前是) Ioc容器(现在的控制权) 控制反转Ioc(Invertion of ...12. 定义IoC容器管理的javabean的生命周期回调方法 13. 接口FactoryBean的使用

    J2EE中文版指南 CHM格式 带全文检索

    确定应用程序客户端的回调处理机制 232 六.EIS(Enterprise Information System)层安全 232 配置契约 232 容器管理的契约 232 组件管理的契约 233 配置资源适配器安全 233 七.传递安全身份 234 配置组件使用的...

    Spring 3 Reference中文

    4.6.1 生命周期回调. 69 4.6.1.1 初始化回调 70 4.6.1.2 销毁回调.. 70 4.6.1.3 默认的初始化和销毁方法 71 4.6.1.4 组合生命周期机制.. 72 4.6.1.5 启动和关闭回调 73 4.6.1.6 在非...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    10.8.1 实体的生命周期与回调事件 444 10.8.2 使用专门的监听器实现回调 448 10.8.3 为全部实体配置默认监听器 450 10.8.4 排除监听器 452 10.9 本章小结 455 第11章 JPA的查询支持 456 11.1 查询API 457 11.1.1 ...

    DWR.xml配置文件说明书(含源码)

    DWR共有三种Creator,最简单的”new”是调用bean的默认构造函数创建实例.”scripted”允许采用其他脚本语言创建实例.如BeanShell.在远程bean的默认构造函数不能进行进一步配置的情况下这种类型的creator比较有用.”...

    Spring.3.x企业应用开发实战(完整版).part2

    8.3.1 使用模板和回调机制 8.3.2 Spring为不同持久化技术所提供的模板类 8.4 数据源 8.4.1 配置一个数据源 8.4.2 获取JNDI数据源 8.4.3 Spring的数据源实现类 8.5 小结 第9章 Spring的事务管理 9.1 数据库事务基础...

    Spring3.x企业应用开发实战(完整版) part1

    8.3.1 使用模板和回调机制 8.3.2 Spring为不同持久化技术所提供的模板类 8.4 数据源 8.4.1 配置一个数据源 8.4.2 获取JNDI数据源 8.4.3 Spring的数据源实现类 8.5 小结 第9章 Spring的事务管理 9.1 数据库事务基础...

    超级有影响力霸气的Java面试题大全文档

     SessionBean: Stateless Session Bean 的生命周期是由容器决定的,当客户机发出请求要建立一个Bean的实例时,EJB容器不一定要创建一个新的Bean的实例供客户机调用,而是随便找一个现有的实例提供给客户机。...

    Spring-Reference_zh_CN(Spring中文参考手册)

    12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用服务器...

    Spring中文帮助文档

    3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 ...

    java 面试题 总结

    但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地...

    Spring API

    3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 ...

    Spring 2.0 开发参考手册

    12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用...

    spring chm文档

    12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用...

    Hibernate实战(第2版 中文高清版)

     12.3.4 实体监听器和回调   12.4 小结   第13章 优化抓取和高速缓存   13.1 定义全局抓取计划   13.1.1 对象获取选项   13.1.2 延迟的默认抓取计划   13.1.3 理解代理   13.1.4 禁用代理生成   ...

    Java开发技术大全 电子版

    4.10.3抽象方法与回调函数171 4.11最终类与最终方法173 4.12接口与多重继承174 4.12.1接口的定义174 4.12.2接口的继承175 4.12.3接口的实现177 4.13内部类179 4.13.1内部类的定义179 4.13.2内部类访问外部类...

    spring3.1中文参考文档

    2.5.3.1 基于Java的bean元数据.................................................................................................. 25 2.5.3.2 使用组件定义bean的元数据.........................................

    play框架手册

    回调Callbacks - 91 - HTTP response流 streaming - 92 - 使用WebSockets - 92 - 11.在play框架里使用Ajax - 94 - 通过jsAction标签使用jQuery - 95 - 12. Internationalization国际化支持 - 96 - 仅使用 UTF-8! - ...

Global site tag (gtag.js) - Google Analytics