[Spring实战系列](10)初探Bean生命周期

1. 生命周期流程图

Bean在Spring容器中从创建到销毁经历了若干个阶段,在每一个阶段都可以针对Spring如何管理Bean进行个性化定制。

正如你所见,在Bean 准备就绪之前,Bean 工厂执行了若干启动步骤。

  • Spring 对Bean 进行实例化。
  • Spring 将值和Bean 的引用注入进Bean 对应的属性中。
  • 如果Bean 实现了BeanNameAware接口,Spring 将Bean的ID传递给setBeanName() 接口方法。
  • 如果Bean 实现了BeanFactoryAware接口,Spring 将调用setBeanFactory()接口方法,将BeanFactory 容器实例传入。
  • 如果Bean 实现了ApplicationContextAware 接口,Spring 将调用setApplicationContext()接口方法,将应用上下文的引用传入。
  • 如果Bean 实现了BeanPostProcessor 接口,Spring 将调用它们的postProcessBeforeInitialization() 接口方法。
  • 如果Bean 实现了InitializingBean 接口,Spring 将调用它们的afterPropertiesSet() 接口方法。类似地,如果Bean 使用init-method 声明了初始化方法,该方法也会被调用。
  • 如果Bean 实现了BeanPostProcessor 接口,Spring 将调用它们的postPoressAfterInitialization() 接口方法。
  • 此时此刻,Bean 已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁。
  • 如果Bean 实现了DisposableBean 接口,Spring 将调用它的destroy()接口方法。同样,如果Bean 使用destroy-method 声明了销毁方法,该方法也会被调用。

2. 各种接口方法分类

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

方法 用途
Bean自身的方法 这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法
Bean级生命周期接口方法 这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
容器级生命周期接口方法 这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
工厂后处理器接口方法 这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

 

3. 实例

我们用一个简单的Spring Bean来演示一下Spring Bean的生命周期。

首先是一个简单的Spring Bean,它实现了BeanNameAware,BeanFactoryAware,InitializingBean,ApplicationContextAware和DiposableBean这5个接口,同时有2个方法(myInit()方法和myDestroy方法),对应配置文件中<bean>的init-method和destroy-method。


package com.sjf.bean;

 

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.BeanFactory;

import org.springframework.beans.factory.BeanFactoryAware;

import org.springframework.beans.factory.BeanNameAware;

import org.springframework.beans.factory.DisposableBean;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

 

/**

 * Student实体类

 * @author sjf0115

 *

 */

public class Student implements BeanNameAware,BeanFactoryAware,InitializingBean,ApplicationContextAware, DisposableBean{

	

	private String name;

	private int age;

	private String school;

	

	// 构造器

	public Student(){

		System.out.println("constructor Student...");

	}

	

	public void setName(String name) {

		this.name = name;

		System.out.println("setName...");

	}

 

	public void setAge(int age) {

		this.age = age;

		System.out.println("setAge...");

	}

 

	public void setSchool(String school) {

		this.school = school;

		System.out.println("setSchool...");

	}

 

	public void myInit(){

		System.out.println("init-method...");

	}

	

	public void myDestroy(){

		System.out.println("destroy-method...");

	}

	

	// 来自于BeanNameAware接口

	public void setBeanName(String arg0) {

		System.out.println("setBeanName...[" + arg0 + "]");

	}

	

	// 来自于BeanFactoryAware接口

	public void setBeanFactory(BeanFactory arg0) throws BeansException {

		System.out.println("setBeanFactory...");

	}

	

	// 来自于InitializingBean

	public void afterPropertiesSet() throws Exception {

		System.out.println("afterPropertiesSet...");

	}

	

	// 来自于DisposableBean

	public void destroy() throws Exception {

		System.out.println("destroy...");

	}

	// 来自于ApplicationContextAware接口

	public void setApplicationContext(ApplicationContext arg0) throws BeansException {

		System.out.println("setApplicationContext...");

	}

	

	@Override

	public String toString() {

		return "name:" + name + "   age:" + age + "   school:" + school;

	}

}

然后是自定义一个MyBeanPostProcessor Bean,实现了BeanPostProcessor接口。


package com.sjf.bean;

 

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.config.BeanPostProcessor;

 

/**

 * 自定义BeanPostProcessor

 * @author sjf0115

 *

 */

public class MyBeanPostProcessor implements BeanPostProcessor{

	

	public MyBeanPostProcessor(){

		System.out.println("constructor MyBeanPostProcessor...");

	}

	

	// 来自于BeanPostProcessor接口

	public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException {

		System.out.println("postProcessAfterInitialization...[" + arg1 + "]");

		return arg0;

	}

		

	// 来自于BeanPostProcessor接口

	public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException {

		System.out.println("postProcessBeforeInitialization...[" + arg1 + "]");

		return arg0;

	}	

}

BeanPostProcessor接口包括2个方法postProcessAfterInitialization()和postProcessBeforeInitialization(),这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。返回值也都是要处理的Bean对象。

接口中的两个方法都要将传入的bean返回,而不能返回null,如果返回的是null那么我们通过getBean方法将得不到目标。

一般ApplicationContext会自动检查是否在定义文件中有实现了BeanPostProcessor接口的类,如果有的话,Spring容器会在每个Bean(其他的Bean)被初始化之前和初始化之后,分别调用实现了BeanPostProcessor接口的类的postProcessAfterInitialization()方法和postProcessBeforeInitialization()方法,对Bean进行相关操作。刚开始只定义了Student一个bean,并且实现了BeanPostProcessor接口,并不会调用postProcessAfterInitialization()和postProcessBeforeInitialization()方法,这时ApplicationContext找不到实现了BeanPostProcessor接口的类。所以这里一个Bean用来实现BeanPostProcessor接口,然后另一个Bean用来配合实现了BeanPostProcessor接口的Bean。

网友的疑问以及解答:http://bbs.csdn.net/topics/300121037

配置文件applicationContext.xml:


<?xml version="1.0" encoding="UTF-8"?>

<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">

	

	<bean id = "yoona" class = "com.sjf.bean.Student" scope="singleton" init-method="myInit" destroy-method="myDestroy">

		<property name="name" value="yoona"/>

		<property name="age" value="24"/>

		<property name="school" value="西电"/>

	</bean>

	

	<bean id = "myBeanPostProcessor" class="com.sjf.bean.MyBeanPostProcessor"/>

</beans>

测试代码:


package com.sjf.bean;

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

 

/**

 * 测试类

 * @author sjf0115

 *

 */

public class Test {

 

	private static ApplicationContext context;

	private static Student stu;

	

	public static void main(String[] args) {

		context = new ClassPathXmlApplicationContext("applicationContext.xml");

		// 2. 从IOC容器中获取Bean实例

		stu = (Student)context.getBean("yoona");

		// 3.调用listAllBook方法

		System.out.println(stu.toString());

		// 4.关闭容器

		((ClassPathXmlApplicationContext) context).registerShutdownHook();

	}

}

运行结果:


constructor MyBeanPostProcessor...

constructor Student...

setName...

setAge...

setSchool...

setBeanName...[yoona]

setBeanFactory...

setApplicationContext...

postProcessBeforeInitialization...[yoona]

afterPropertiesSet...

init-method...

postProcessAfterInitialization...[yoona]

name:yoona   age:24   school:西电

destroy...

destroy-method...

从这个运行结果中我们就可以看出一个Bean的生命周期:constructor(实例化) -> setXXX(填充属性) -> BeanName(BeanNameAware接口) -> BeanFactory(BeanFactoryAware接口)
-> ApplicationContext(ApplicationContextAware接口) -> postProcessBeforeInitialization(BeanPostProcessor接口) -> afterPropertiesSet(InitializingBean接口)
-> init-method(定制的初始化方法) -> postProcessAfterInitialization(BeanPostProcessor接口) -> destroy(DisposableBean接口)
-> destroy-method(定制的销毁方法)

来源于:《Spring实战》

时间: 2024-10-19 10:31:21

[Spring实战系列](10)初探Bean生命周期的相关文章

从启动日志看Spring IOC的初始化和Bean生命周期

一.Tomcat中启动IoC容器的日志 启动Tomcat等容器时,控制台每次都打印出一些日志. 最近刚好在研究Spring源码,所以换个角度,从启动日志来简单的看看Spring的初始化过程! 以下是Tomcat启动时日志,截取Spring部分. //------------------------------------- //从这里开始Spring的初始化 十一月 10, 2015 8:52:03 上午 org.apache.catalina.core.ApplicationContext l

Spring Framework核心概念之Bean生命周期管理

目录 Spring Bean的生命周期 相关接口的分类 测试SpringBean生命周期的Demo程序 小结 Spring Bean的生命周期 Spring容器既Application或者WebApplication会在管理Bean的时候:为了尽可能的把自己内部的东西机制暴露出来给用户使用,所以在Bean创建的过程中加了很多机制,通过所谓的"处理器"Processor暴露出来,然后处理器都有自己的顺序,我们需要做的就是定义好处理器的逻辑,然后注册到Sprinhg容器中,Spring就会

一步步剖析spring bean生命周期

关于spring bean的生命周期,是深入学习spring的基础,也是难点,本篇文章将采用代码+图文结论的方式来阐述spring bean的生命周期, 本篇文章将阐述清楚下图. 一  项目结构及源码 1.程序目录结构 2.applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/sc

Spring点滴四:Spring Bean生命周期

Spring Bean 生命周期示意图: 了解Spring的生命周期非常重要,我们可以利用Spring机制来定制Bean的实例化过程. --------------------------------------------------------------------------------------------------------------------------------------------------- spring-service.xml: <?xml version=

【Spring学习】Bean生命周期

我理解的Bean生命周期包括两个方面: Bean何时创建,何时销毁 Bean从创建到销毁的执行流程 一.Bean创建与销毁 Bean的创建时机主要由几个配置项共同来决定,包括: scope属性,决定是Bean是单例模式(singleton)还是多例模式(prototype),默认为单例singleton: lazy-init属性,只对单例模式有效,决定是否延时加载,默认为false,表示在容器初始化时,就会生成单例: RequestMapping属性,这个注解MVC中才有,当有该属性时,lazy

Spring事务,Bean生命周期

一.事务相关: 1.Spring事务基于Spring AOP切面编程: 2.AOP基于代理模式,得到需要开启事务的代码的代理对象: 3.而没有开启事务的Service方法里调用了开启事务 @Transactional 的方法时,整个代码是不会开启事务的,原理还是代理模式插入事务的依据是最外层的注解: 4.对于上面3,反之,则可以,这是事务的传播机制. 二.Bean生命周期: 2.1生命周期图: 出自:<精通Spring 4.x> 2.2不同级别的接口分类: 1.Bean本身的方法:Bean的构

bean生命周期

那在spring中bean的生命周期究竟是怎样的呢 1. 容器寻找Bean的定义信息并将其实例化 2. 使用依赖注入,spring按照Bean定义信息配置Bean的所有属性 3. 如果Bean实现了BeanNameAware接口,工厂调用Bean的SetBeanName()方法传递Bean的ID 4. 如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身 5. 如果BeanPostProcessor和Bean关联,那么其postProc

Spring基础系列10 -- Spring AOP-----------Pointcut, Advisor

Spring基础系列10 -- Spring AOP-----------Pointcut, Advisor 转载:http://www.cnblogs.com/leiOOlei/p/3557643.html 上一篇的Spring AOP Advice例子中,Class(CustomerService)中的全部method都被自动的拦截了.但是大多情况下,你只需要一个方法去拦截一两个method.这样就引入了Pointcut(切入点)的概念,它允许你根据method的名字去拦截指定的method

Bean 生命周期

对于普通的Java对象,当new的时候创建对象,当它没有任何引用的时候被垃圾回收机制回收.而由Spring IoC容器托管的对象,它们的生命周期完全由容器控制. Bean生命周期流程 1.实例化Bean 实例化Bean对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化. 对于ApplicationContext容器,当容器启动结束后,便实例化所有的bean. 容器通过获取B