1. 生命周期流程图
2.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 声明了销毁方法,该方法也会被调用。
3实例
首先是一个简单的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;
}
}
配置文件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(定制的销毁方法)
总结
- 步骤1,2,是new一个bean,创建bean的构造函数,并对bean的属性和引用进行创建。
- 步骤3,是设置bean的标识,提供回调自身的能力。
- 步骤 4,5 ,是选择一直IOC容器初始化的方式,通过BeanFactor初始化或者ApplicationContext。
- 步骤 6,7,8。是Bean初始化和初始化之前和之后的一些操作。 实现Initialization ,实现afterPropertiesSet方法。BeanPostProcessor 的接口包含了BeanInit之前和之后的方法。
- 步骤9 ,是Bean时间示例好了,可以供应用程序使用了。
- 步骤10,是Bean的销毁,实现 DisposableBean接口。
- init-method 和 destroy-method 是用户自定义的初始化和销毁方法。
Aware相关接口
1.1、Spring提供一些Aware接口:
beanNameAware接口:如果某个bean需要访问配置文件中本身bean的id属性,这个Bean类通过实现该接口,在依赖关系确定之后,初始化方法之前,提供回调自身的能力,从而获得本身bean的id属性,该接口提供了void setBeanName(String name)方法实现,需要指出的是该方法的name参数就是该bean的id属性,加调该setBeanName方法可以让bean获取得自身的id属性
BeanFactoryAware接口:实现了BeanFactoryAware接口的bean,可以直接通过beanfactory来访问spring的容器,当该bean被容器创建以后,会有一个相应的beanfactory的实例引用,该 接口有一个方法void setBeanFactory(BeanFactory beanFactory)方法通过这个方法的参数创建它的BeanFactory实例,实现了BeanFactoryAware接口,就可以让Bean拥有访问Spring容器的能力。缺点:导致代码与spring的api耦合在一起,这种方式不推荐。
ApplicationContextAware接口:在Bean类被初始化后,将会被注入applicationContext实例,该接口有一个方法,setApplicationContext(ApplicationContext context),使用其参数context用来创建它的applicationContext实例,缺点:导致代码与spring的api耦合在一起,这种方式不推荐。
二、BeanPostProcessor类 和BeanFactoryPostProcessor
对容器中的Bean进行处理,实现BeanPostProcessor接口Bean后处理器
// 第一个参数初始化的Bean第二个参数是Bean 实例的名称
public Object postProcessAfterInitialization(Object arg0, String arg1);在bean初始化之后的操作
public Object postProcessBeforeInitialization(Object arg0, String arg1);在bean初始化之前的操作
容器后处理器在容器实例化结束后,对容器进行额外的处理,必须实现BeanFactoryPostProcessor接口,
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
//Spring撮提供了很多后窗口处理器如:
//PropertyPlaceholderConfigurer:属性占位符配置器
//PropertyOverrideConfigurer:另外一种属性占位符配置器
2种的区别在与后面一种具有覆盖的性质