什么是bean的生命周期?
Spring是一个容器, bean是存在于容器中被管理的对象。bean的生命周期就是指bean从实例化到被设置属性,再到容器销毁时bean被销毁的整个过程。
为什么要了解bean的生命周期?
Spring 就是面向 Bean 的编程。如果把Spring比做一个舞台,那么bean就是舞台上的演员。Spring 作为Java中最优秀的框架之一,已被广泛的使用,很多第三方框架在设计的时候都考虑到了和Spring的集成,集成的根本其实就是在Spring容器中定义bean。而作为一个优秀的框架,Spring很多设计思想都独具匠心,在bean的整个生命周期过程中预留了很多扩展接口和自定义处理,掌握了bean的生命周期不仅可以学习优秀的设计模式,而且对理解 Spring 框架原理有非常好的作用,有助于深入理解Ioc和AOP。
bean生命周期详解
bean的生命周期不就是实例化,设置属性,使用完以后被销毁这么简单吗?实例化就是调用类的构造方法,设置属性就是调用setter方法注入,销毁甚至可以不用定义destroy方法。那么还有那么多要了解的么?
日常开发中我们定义最多的就是下面这种业务bean,这类bean的生命周期的确很简单
<bean id="xxService" class="com.xx.xx.service.impl.xxServiceImpl"/>
除了这类bean的定义,我们在搭建Spring框架时其实还定义了很多bean。其中涉及到
BeanNameAware, BeanFactoryAware, BeanFactoryPostProcessor,InitializingBean, DisposableBean等各种生命周期接口。例如
属性加载器定义:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>${jdbc.driverClassName}</value>
</property>
...
</bean>
线程池定义:
<bean id ="asyncExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="20" />
<property name="keepAliveSeconds" value="200" />
<property name="maxPoolSize" value="300" />
<property name="queueCapacity" value="300" />
<property name="threadNamePrefix" value="test_asynchronousExecutor" />
<property name="threadGroupName" value="test_asynchronousExecutorGroup" />
</bean>
下面我们详细介绍bean的生命周期过程
-
生命周期流程
各种生命周期接口方法分类
Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
1)Bean自身的方法:这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法
2)Bean级生命周期接口方法:这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
3)容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
4)工厂后处理器接口方法:这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器 接口的方法。工厂后处理器也是容器级的。在容器启动装配配置文件之后立即调用。 (PropertyPlaceholderConfigurer其实就是一个工厂后处理器接口的实现)
3.代码演示
1)定义一个bean,调用Bean自身的方法和Bean级生命周期接口方法。它实现了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口,同时有2个方法,对应配置文件中<bean>的init-method和destroy-method
public class Person implements BeanFactoryAware, BeanNameAware,
InitializingBean, DisposableBean {
private String name;
private String address;
private int phone;
private BeanFactory beanFactory;
private String beanName;
public Person() {
System.out.println("【构造器】调用Person的构造器实例化");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("【注入属性】注入属性name");
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
System.out.println("【注入属性】注入属性address");
this.address = address;
}
public int getPhone() {
return phone;
}
public void setPhone(int phone) {
System.out.println("【注入属性】注入属性phone");
this.phone = phone;
}
@Override
public String toString() {
return "Person [address=" + address + ", name=" + name + ", phone="
+ phone + "]";
}
// 这是BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out
.println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
this.beanFactory = arg0;
}
// 这是BeanNameAware接口方法
@Override
public void setBeanName(String arg0) {
System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
this.beanName = arg0;
}
// 这是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out
.println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
}
// 这是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
}
// 通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
}
// 通过<bean>的destroy-method属性指定的初始化方法
public void myDestory() {
System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
}
}
2)容器级生命周期接口BeanPostProcessor。BeanPostProcessor接口包括2个方法postProcessAfterInitialization和postProcessBeforeInitialization,这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。返回值也都是要处理的Bean对象
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
super();
System.out.println("这是BeanPostProcessor实现类构造器!!");
}
@Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException {
System.out
.println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!");
return arg0;
}
@Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException {
System.out
.println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!");
return arg0;
}
}
3)工厂后处理器接口方法
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
throws BeansException {
System.out
.println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
BeanDefinition bd = arg0.getBeanDefinition("person");
bd.getPropertyValues().addPropertyValue("phone", "110");
}
}
4)配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="beanPostProcessor" class="springBeanTest.MyBeanPostProcessor">
</bean>
<bean id="beanFactoryPostProcessor" class="springBeanTest.MyBeanFactoryPostProcessor">
</bean>
<bean id="person" class="springBeanTest.Person" init-method="myInit"
destroy-method="myDestory" scope="singleton" p:name="张三" p:address="武汉"
p:phone="15900000000" />
</beans>
5)测试代码
public class BeanLifeCycle {
public static void main(String[] args) {
System.out.println("现在开始初始化容器");
ApplicationContext factory = new ClassPathXmlApplicationContext("springBeanTest/beans.xml");
System.out.println("容器初始化成功");
//得到Preson,并使用
Person person = factory.getBean("person",Person.class);
System.out.println(person);
System.out.println("现在开始关闭容器!");
((ClassPathXmlApplicationContext)factory).registerShutdownHook();
}
}
运行结果:
现在开始初始化容器
这是BeanFactoryPostProcessor实现类构造器!!
BeanFactoryPostProcessor调用postProcessBeanFactory方法
这是BeanPostProcessor实现类构造器!!
【构造器】调用Person的构造器实例化
【注入属性】注入属性address
【注入属性】注入属性name
【注入属性】注入属性phone
【BeanNameAware接口】调用BeanNameAware.setBeanName()
【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()
BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!
【InitializingBean接口】调用InitializingBean.afterPropertiesSet()
【init-method】调用<bean>的init-method属性指定的初始化方法
BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!
容器初始化成功
Person [address=武汉, name=张三, phone=110]
现在开始关闭容器!
【DiposibleBean接口】调用DiposibleBean.destory()
【destroy-method】调用<bean>的destroy-method属性指定的初始化方法
现在回过头来看看propertyConfigurer这个bean,它其实不是普通的bean,就是一个工厂后处理器,在容器启动的时候,它的postProcessBeanFactory方法被调用,方法逻辑就是从配置的locations路径中寻找properties文件,将文件内容转换为map对象,然后将容器中其他所有bean(其他是指非容器级生命周期接口的bean和非工厂后处理器的bean) <property>中的占位符替换成配置文件中的值。等到所有占位符替换完成,bean就可以正常的初始化了。
说到bean的生命周期,不得不提一下FactoryBean接口,它和BeanFactory名字非常类似,但是含义却千差万别。 它是一个特殊的接口,实现了此接口的bean,容器将调用接口的getObject()方法得到该bean对象,而不是调用类的构造方法。除此之外,其他生命周期和前面描述的一样。
FactoryBean实际应用:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="xxx_master" />
<property name="mapperLocations">
<array>
<value>classpath*:mapper/**/*.xml</value>
</array>
</property>
</bean>