`

Spring(08)——bean生命周期回调方法

阅读更多

8生命周期回调方法

对于Spring bean来讲,我们默认可以指定两个生命周期回调方法。一个是在ApplicationContextbean初始化,包括注入对应的依赖后的回调方法;另一个是在ApplicationContext准备销毁之前的回调方法。要实现这种回调主要有三种方式:实现特定的接口、在XML配置文件中指定回调方法和使用JSR-250标准的注解。

8.1 实现特定接口

针对bean初始化后的回调和ApplicationContext销毁前的回调,Spring分别为我们了提供了InitializingBeanDisposableBean接口供用户实现,这样Spring在需要进行回调时就会调用对应接口提供的回调方法。

8.1.1 InitializingBean

InitializingBean是用来定义ApplicationContext在完全初始化一个bean以后需要需要回调的方法的,其中只定义了一个afterPropertiesSet()方法。如其名称所描述的那样,该方法将在ApplicationContext将一个bean完全初始化,包括将对应的依赖项都注入以后才会被调用。InitializingBean的完全定义如下。

public interface InitializingBean {

	void afterPropertiesSet() throws Exception;

}

由于InitializingBeanafterPropertiesSet()方法会在依赖项都进行注入以后再回调,所以该方法通常会用来检查必要的依赖注入,以使我们能够在bean被初始化时就发现其中的错误,而不是在很长时间使用以后才发现。如果你去看Spring的源码,你就会发现源码中有很多InitializingBean的使用,而且基本都是用来检查必要的依赖项是否为空的。

public class Hello implements InitializingBean {
	
	private World world;
	
	/**
	 * 该方法将在当前bean被完全初始化后被调用
	 */
	public void afterPropertiesSet() throws Exception {
		Assert.notNull(world, "world should not be null.");
	}

	public void setWorld(World world) {
		this.world = world;
	}
	
}

8.1.2 DisposableBean

DisposableBean是用来定义在ApplicationContext销毁之前需要回调的方法的。DisposableBean接口中只定义了一个destroy()方法,在ApplicationContext被销毁前,Spring将依次调用bean容器中实现了DisposableBean接口的destroy()方法。所以,我们可以通过实现该接口的destroy()方法来达到在ApplicationContext销毁前释放某些特定资源的目的。

public interface DisposableBean {

	void destroy() throws Exception;

}

Spring的源码中,也有很多实现了DisposableBean接口的类,如我们熟悉的ApplicationContext实现类、SingleConnectionDataSource等。

8.2 在XML中配置回调方法

XML配置文件中通过bean元素定义一个bean时,我们可以通过bean元素的init-method属性和destroy-method属性来指定当前bean在初始化以后和ApplicationContext销毁前的回调方法。需要注意的是所指定的回调方法必须是没有参数的。
通过init-method属性来指定初始化方法时所对应的方法必须是该bean中所拥有的方法,所以首先我们需要在对应的bean中定义对应的初始化方法,这里假设我们需要在bean中定义一个init()方法作为该bean的初始化方法,那么我们可以对我们的bean进行类似如下定义。

public class Hello {
	
	private World world;
	
	/**
	 * 该方法将被用来作为初始化方法,在当前bean被完全初始化后被调用
	 */
	public void init() {
		Assert.notNull(world, "world should not be null.");
	}

	public void setWorld(World world) {
		this.world = world;
	}
	
}

接下来就是在XML配置文件中定义该bean时通过init-method属性定义对应的初始化方法为init()方法,init-method属性的属性值就对应初始化方法的名称,所以我们的bean应该是如下定义。

	<bean name="world" class="com.app.World"/>
	<!-- 通过init-method属性指定初始化方法名称 -->
	<bean id="hello" class="com.app.Hello" init-method="init">
		<property name="world" ref="world"/>
	</bean>

init-methoddestroy-method的用法和配置等基本上都是一样的,所以对于使用destroy-method来指定ApplicationContext销毁前的回调方法的用法就不再赘述了。

如果我们的初始化方法或销毁方法的名称大都是一样的,在通过init-methoddestroy-method进行指定的时候我们就没有必要一个个bean都去指定了,Spring允许我们在最顶级的beans元素上指定默认的初始化后回调方法和销毁前的回调方法名称,这样对于没有指定init-methoddestroy-method的bean将默认将其中default-init-methoddefault-destroy-method属性值对应名称的方法(如果存在的话)视为初始化后的回调方法或销毁前的回调方法。这是通过default-init-methoddefault-destroy-method属性来定义的。

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd"
    default-init-method="init" default-destroy-method="destroy">
	
</beans>

以上表示定义默认的初始化后回调方法名称为init,默认的销毁前回调方法名称为destroy。
当定义了default-init-methoddefault-destroy-method以后,如果我们的某个bean对应的初始化后回调方法名称或销毁前的回调方法名称与默认定义的不一样,则我们可以在对应的bean上通过init-methoddestroy-method指定该bean自身的回调方法名称,即bean上定义的回调方法名称将会比默认定义拥有更高的优先级。

8.3 使用JSR-250标准的注解

关于bean的生命周期回调方法,Spring也会JSR-250标准注解做了支持,即在bean完全初始化后将回调使用@PostConstruct标注的方法,在销毁ApplicationContext前将回调使用@PreDestroy标注的方法。
针对之前的示例,如果我们现在把定义的bean定义成如下这样,即没有在bean上通过init-methoddestroy-method指定初始化方法和销毁方法。

	<bean name="world" class="com.app.World"/>
	<bean id="hello" class="com.app.Hello">
		<property name="world" ref="world"/>
	</bean>

当然,这里也不考虑全局性的init-methoddestroy-method方法,如果我们希望在id为“hello”的bean被初始化后回调其中的init()方法,在销毁前回调其中的destroy()方法,我们就可以通过@PostConstruct@PreDestroy进行如下定义。

public class Hello {
	
	private World world;
	
	/**
	 * 该方法将被用来作为初始化方法,在当前bean被完全初始化后被调用
	 */
	@PostConstruct
	public void init() {
		Assert.notNull(world, "world should not be null.");
	}
	
	@PreDestroy
	public void destroy() {
		System.out.println("---------destroy-----------");
	}

	public void setWorld(World world) {
		this.world = world;
	}
	
}

使用JSR-250标准指定初始化后的回调方法以及销毁前的回调方法时,如果我们希望将多个方法都作为对应的回调方法进行回调,则可以在多个方法上同时使用对应的注解进行标注,Spring将依次执行对应的方法。

public class Hello {
	
	private World world;

	@PostConstruct
	public void init() {
		System.out.println("-----------init-------------");
	}
	
	/**
	 * 该方法将被用来作为初始化方法,在当前bean被完全初始化后被调用
	 */
	@PostConstruct
	public void init2() {
		Assert.notNull(world, "world should not be null.");
	}
	
	@PreDestroy
	public void destroy() {
		System.out.println("------------destroy----------------");
	}
	
	@PreDestroy
	public void destroy2() {
		System.out.println("---------destroy2-----------");
	}

	public void setWorld(World world) {
		this.world = world;
	}
	
}

8.4 混合使用三种方式

Spring允许我们混合使用上述介绍的三种方式来指定对应的回调方法。当对于同一个bean使用三种方式指定了同一个方法作为初始化后的回调方法或销毁前的回调方法,则对应的回调方法只会被执行一次。然而,当对于同一个bean使用两种或三种方式指定的回调方法不是同一个方法时,Spring将依次执行使用不同的方式指定的回调方法。对于初始化后的回调方法而言,具体规则如下:

  • 使用@PostConstruct标注的方法。
  • 实现InitializingBean接口后的回调方法afterPropertiesSet()方法。
  • 通过init-method或default-init-method指定的方法。

对于销毁前的回调方法而言,其规则是一样的:

  • 使用@PreDestroy标注的方法。
  • 实现DisposableBean接口后的回调方法destroy()方法。
  • 通过destroy-method或default-destroy-method指定的方法。

(注:本文是基于Spring4.1.0所写)

 

 

本文转自:https://elim.iteye.com/blog/2384787

分享到:
评论

相关推荐

    spring bean的生命周期

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

    详解Spring中bean生命周期回调方法

    Spring 中 Bean 生命周期回调方法详解 Spring 中 Bean 的生命周期回调方法是指在 Bean 的生命周期中, Spring 框架提供了多种方式来实现对 Bean 的生命周期的管理。这些回调方法可以在 Bean 的初始化、销毁等阶段被...

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

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

    Spring bean生命周期demo

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

    spring bean的生命周期测试代码

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

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

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

    Spring管理的Bean的生命周期

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

    Spring Bean生命周期&BeanDefinitions1

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

    Spring Bean 的生命周期

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

    spring bean life cycle

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

    Spring Bean 的生命周期.docx

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

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

    这个顺序在实际应用中非常重要,因为它确保了在Bean生命周期的不同阶段,开发者可以按照需求执行相应的清理工作或数据校验等操作。在上述测试中,我们观察到了这个顺序,它为理解Spring Bean的生命周期提供了直观的...

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

    实例化过程是Bean生命周期的起点。 2. **依赖注入**: - 在Bean实例化后,Spring会执行依赖注入(Dependency Injection,DI),将所需的属性值注入到Bean中。这可以通过setter方法、构造函数或者字段注入实现。 3...

    Spring学习笔记之bean生命周期

    《Spring学习笔记之bean生命周期》 在Spring框架中,Bean是核心组件,它们构成了应用程序的主要结构。理解Spring Bean的生命周期对于有效地管理和优化Spring应用程序至关重要。本文将深入探讨Spring Bean的生命周期...

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

    实现`BeanPostProcessor`接口可以让开发者在Bean生命周期的关键时刻插入自定义逻辑,比如验证、缓存管理、AOP代理等。这提供了高度的灵活性,但同时也需要谨慎处理,因为不恰当的处理可能会影响到整个应用的性能和...

    Bean的生命周期介绍

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

    day38 09-Spring类的完整生命周期及后处理Bean

    Bean的实例化是生命周期的第一步,Spring支持多种实例化方式,如无参构造器、工厂方法等。当通过XML配置时,Spring会使用无参构造器来创建Bean。如果Bean定义了工厂方法,那么Spring会调用该方法来获取Bean的实例。...

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

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

    bean的生命周期分析(五)

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

Global site tag (gtag.js) - Google Analytics