`
dylan0514sina.cn
  • 浏览: 94905 次
  • 性别: 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
分享到:
评论

相关推荐

    spring bean的生命周期

    Spring Bean的生命周期是Spring框架...在实际开发中,可以利用生命周期回调方法进行一些初始化和清理工作,提高代码的健壮性和可维护性。同时,结合日志记录,可以跟踪和分析Bean的整个生命周期,进一步优化系统性能。

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

    在Spring框架中,Bean的生命周期管理和作用域是其核心特性之一,它们对于理解Spring如何管理对象的...在实际开发中,根据业务需求选择合适的作用域,并善用生命周期回调方法,可以使Spring更好地服务于我们的应用程序。

    Spring bean生命周期demo

    在Spring框架中,Bean的生命周期是指从创建到销毁的整个过程。这个过程包含了初始化、正常使用...通过合理的配置和回调方法,我们可以更好地控制Bean的创建、初始化、使用和销毁,从而实现更加灵活和高效的代码管理。

    spring bean的生命周期测试代码

    4. **容器回调**:在Bean初始化之后,Spring容器可能会调用自己的回调方法,如`BeanPostProcessor`接口实现的`postProcessBeforeInitialization()`和`postProcessAfterInitialization()`方法,允许自定义逻辑进一步...

    Spring Bean生命周期&BeanDefinitions1

    3. **Bean接口回调**:如果Bean实现了特定的接口,如`BeanNameAware`、`BeanFactoryAware`或`ApplicationContextAware`,Spring会在适当的时候调用对应的回调方法。这些接口允许Bean获取其ID、BeanFactory引用或...

    基于java的企业级应用开发:Bean的生命周期.ppt

    3. **Bean接口回调**: - 如果Bean实现了特定的Spring接口,如`BeanNameAware`,`BeanFactoryAware`,`ApplicationContextAware`,Spring会在适当的时间调用相应的方法。 - `BeanNameAware`的`setBeanName()`方法...

    Spring Bean 的生命周期

    - **关联实际场景**:将每个阶段与实际编程中的例子关联起来,比如实例化对应创建对象,属性注入对应依赖注入,初始化回调对应启动服务,销毁回调对应关闭资源。 - **图表辅助**:可以绘制一个流程图,直观展示Bean...

    SSH笔记-IOC容器中 Bean 的生命周期

    4. **初始化回调**:如果在Bean定义中指定了`init-method`,Spring会在所有`BeanPostProcessor`的`postProcessAfterInitialization()`方法执行后调用这个指定的方法。 5. **正常使用**:Bean现在已经被完全初始化,...

    Bean的生命周期介绍

    3. **BeanPostProcessor.postProcessBeforeInitialization**:这是一个允许开发者自定义处理逻辑的回调方法,通常用于对Bean进行进一步的定制或修改。 - 这个方法会在所有初始化之前调用,包括自定义初始化方法或...

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

    5. **销毁回调**:当Spring容器关闭时,或Bean定义中设置了`destroy-method`,Spring会调用Bean的销毁方法。同样,实现`DisposableBean`接口的Bean会调用`destroy()`方法。 接下来,我们看看ApplicationContext的...

    bean的生命周期分析(五)

    5. **生命周期回调**:在Bean的生命周期中,Spring还提供了销毁回调的方法,如DisposableBean接口的destroy()方法,或者使用@PreDestroy注解的方法。这些方法会在Bean被销毁前执行,提供清理资源的机会。 6. **销毁...

    Spring管理的Bean的生命周期

    总之,Spring管理的Bean生命周期包括创建、初始化、活跃使用和销毁四个主要阶段,通过各种回调方法、接口和注解,我们可以对Bean的行为进行自定义,以满足不同应用场景的需求。深入理解这些机制,有助于我们更好地...

    Spring bean初始化及销毁你必须要掌握的回调方法.docx

    下面将详细介绍如何通过不同方式定义Spring Bean的初始化和销毁回调方法。 **初始化回调方法** 1. **@PostConstruct注解** 这个Java标准注解用于标记一个方法,该方法将在对象完全构造后但在业务逻辑执行前被调用...

    spring bean life cycle

    3. **初始化**:在属性注入完成后,Spring会执行Bean实现的初始化回调方法,这些方法可以通过实现`InitializingBean`接口的`afterPropertiesSet()`方法或者使用`init-method`属性来指定。此外,还可以通过配置`@...

    第四期.Bean的生命周期.zip

    这个过程中,Spring提供了一系列的回调方法和接口,使得开发者可以自定义Bean的行为。以下是对Spring Bean生命周期的详细解释。 首先,Bean的生命周期分为三个主要阶段:初始化、操作和销毁。 1. **初始化阶段**:...

    bean的生命周期1

    这是Spring对那些没有定义初始化和销毁方法的Bean提供的一种回调机制。 3. **使用JSR250注解**: Java标准版中的JSR250规范引入了一些注解,如`@PostConstruct`和`@PreDestroy`,它们可以用来标记初始化和销毁方法...

    Spring Bean 的生命周期.docx

    在这个过程中,Spring容器提供了多个关键接口和回调方法,使得开发者能够自定义Bean的行为。 首先,BeanFactory是Spring中最基础的容器,它负责Bean的实例化。在BeanFactory中,Bean的生命周期主要涉及以下接口: ...

    粗略实现spring创建bean

    - 切面自动代理:Spring能够自动为Bean创建代理,以便在方法调用前后执行额外逻辑。 6. Spring Bean 的装配 - 自动装配:通过`@Autowired`注解自动寻找匹配类型的Bean进行装配。 - 配置文件指定:在XML配置文件...

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

    综上所述,Spring Bean重复执行两次的问题通常是由于配置错误、依赖注入循环、初始化回调的不当使用、静态工厂方法的误用、AOP代理的配置问题或是Bean作用域设置不准确导致的。通过仔细检查和修正这些问题,可以避免...

Global site tag (gtag.js) - Google Analytics