通过前面多个接口的介绍了解了Bean对象生命周期相关的方法,本文就将这些接口的方法串起来,来了解Bean的完整的生命周期。而介绍Bean的生命周期也是面试过程中经常会碰到的一个问题,如果不注意就跳坑里啦~~
Spring之Bean对象的初始化和销毁方法
Spring之InitializingBean接口和DisposableBean接口介绍
Spring之Aware接口介绍
Spring之InstantiationAwareBeanPostProcessor接口介绍
Spring之BeanFactoryPostProcessor接口介绍
Spring之BeanPostProcessor(后置处理器)介绍
建议:看此文前请将上面相关的内容熟悉下,便于理解下面的内容。
接口 | 方法 | 说明 |
---|---|---|
BeanFactoryPostProcessor | postProcessBeanFactory | 在Bean对象实例化之前执行, 通过beanFactory可以获取bean的定义信息, 并可以修改bean的定义信息。这点是和BeanPostProcessor最大区别 |
BeanPostProcessor | postProcessBeforeInitialization | 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务 |
postProcessAfterInitialization | 实例化、依赖注入、初始化完毕时执行 | |
InstantiationAwareBeanPostProcessor | postProcessBeforeInstantiation | 在方法实例化之前执行,返回结果为null正常执行,返回结果如果不为null则会跳过相关方法而进入初始化完成后的流程 |
postProcessAfterInstantiation | 在方法实例化之后执行,返回结果true才会执行postProcessPropertyValues方法 | |
postProcessPropertyValues | 可以用来修改Bean中属性的内容 | |
InitializingBean | afterPropertiesSet | 初始化的方法 |
DisposableBean | destroy | 容器销毁前的回调方法 |
Aware | setXXX | 感知对应Spring容器的内容 |
@PostConstruct | 标注在方法头部,表示初始化的方法 | |
@PreDestroy | 标注在方法头部,表示销毁前回调的方法 | |
init-method属性 | 指定初始化的方法 | |
destory-method属性 | 指定销毁前的回调方法 |
该接口中的方法是最先执行的。在Bean实例化之前执行
/**
* 自定义BeanFactoryPostProcessor
*
* @author dengp
*
*/
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
/**
* 本方法在Bean对象实例化之前执行,
* 通过beanFactory可以获取bean的定义信息,
* 并可以修改bean的定义信息。这点是和BeanPostProcessor最大区别
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("****** BeanFactoryPostProcessor 开始执行了");
/*String[] names = beanFactory.getBeanDefinitionNames();
for (String name : names) {
if("user".equals(name)){
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
// MutablePropertyValues如果设置了相关属性,可以修改,如果没有设置则可以添加相关属性信息
if(propertyValues.contains("name")){
propertyValues.addPropertyValue("name", "bobo");
System.out.println("修改了属性信息");
}
}
}*/
System.out.println("******* BeanFactoryPostProcessor 执行结束了");
}
}
该接口中定义了两个方法,分别在Bean对象实例化及装配后在初始化的前后执行
/**
* 自定义BeanPostProcessor实现类
* BeanPostProcessor接口的作用是:
* 我们可以通过该接口中的方法在bean实例化、配置以及其他初始化方法前后添加一些我们自己的逻辑
* @author dengp
*
*/
public class MyBeanPostProcessor implements BeanPostProcessor{
/**
* 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务
* 注意:方法返回值不能为null
* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象
* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("user".equals(beanName)){
System.out.println(">>后置处理器 before方法:"+bean+"\t"+beanName);
}
// 可以根据beanName不同执行不同的处理操作
return bean;
}
/**
* 实例化、依赖注入、初始化完毕时执行
* 注意:方法返回值不能为null
* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象
* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("user".equals(beanName)){
System.out.println("<<后置处理器after方法:"+bean+"\t"+beanName);
}
// 可以根据beanName不同执行不同的处理操作
return bean;
}
}
该接口是BeanPostProcessor接口的子接口,所以该接口肯定具有BeanPostProcessor接口的功能,同时又定义了三个自己的接口,这三个接口是在Bean实例化前后执行的方法。
/**
* 自定义处理器
* @author dengp
*
*/
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor{
/**
* BeanPostProcessor接口中的方法
* 在Bean的自定义初始化方法之前执行
* Bean对象已经存在了
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
if("user".equals(beanName)){
System.out.println("【---InstantiationAwareBeanPostProcessor---】 postProcessBeforeInitialization");
}
return bean;
}
/**
* BeanPostProcessor接口中的方法
* 在Bean的自定义初始化方法执行完成之后执行
* Bean对象已经存在了
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("user".equals(beanName)){
System.out.println("【--InstantiationAwareBeanPostProcessor----】 postProcessAfterInitialization");
}
return bean;
}
/**
* InstantiationAwareBeanPostProcessor中自定义的方法
* 在方法实例化之前执行 Bean对象还没有
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if("user".equals(beanName)){
System.out.println("【--InstantiationAwareBeanPostProcessor----】postProcessBeforeInstantiation");
}
return null;
}
/**
* InstantiationAwareBeanPostProcessor中自定义的方法
* 在方法实例化之后执行 Bean对象已经创建出来了
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if("user".equals(beanName)){
System.out.println("【--InstantiationAwareBeanPostProcessor----】postProcessAfterInstantiation");
}
return true;
}
/**
* InstantiationAwareBeanPostProcessor中自定义的方法
* 可以用来修改Bean中属性的内容
*/
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,
String beanName) throws BeansException {
if("user".equals(beanName)){
System.out.println("【--InstantiationAwareBeanPostProcessor----】postProcessPropertyValues--->");
}
return pvs;
}
}
Aware接口是用来让对象感知当前的IOC环境
这两个接口是Bean初始化及销毁回调的方法。
package com.dpb.pojo;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
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;
/**
* 实现InitializingBean和DisposableBean接口
* @author dengp
*
*/
public class User implements InitializingBean,DisposableBean,BeanNameAware,BeanFactoryAware{
private int id;
private String name;
//感知本对象在Spring容器中的id属性
private String beanName;
// 感知本对象所属的BeanFactory对象
private BeanFactory factory;
public User(){
System.out.println("构造方法被执行了...User 被实例化");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("《注入属性》注入name属性"+name);
this.name = name;
}
public String getBeanName() {
return beanName;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", beanName=" + beanName + "]";
}
/**
* bean对象销毁前的回调方法
*/
@Override
public void destroy() throws Exception {
// TODO Auto-generated method stub
System.out.println("《DisposableBean接口》destory ....");
}
/**
* 初始化的方法
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化:《InitializingBean接口》afterPropertiesSet....");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
// TODO Auto-generated method stub
System.out.println("【BeanFactoryAware接口】setBeanFactory");
this.factory = beanFactory;
}
@Override
public void setBeanName(String name) {
System.out.println("【BeanNameWare接口】setBeanName");
this.beanName = name;
}
public BeanFactory getFactory() {
return factory;
}
/**
* 也是个初始化的方法
*/
@PostConstruct
public void postConstruct(){
System.out.println("初始化:【@PostConstruct】执行了...");
}
/**
* 销毁前的回调方法
*/
@PreDestroy
public void preDestory(){
System.out.println("【@preDestory】执行了...");
}
/**
* 初始化的方法
* 通过bean标签中的 init-method属性指定
*/
public void start(){
System.out.println("初始化:【init-method】方法执行了....");
}
/**
* 销毁前的回调方法
* 通过bean标签中的 destory-method属性指定
*/
public void stop(){
System.out.println("【destory-method】方法执行了....");
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:annotation-config/>
<bean class="com.dpb.pojo.User" id="user" init-method="start" destroy-method="stop" >
<property name="name" value="波波烤鸭">property>
bean>
<bean class="com.dpb.processor.MyBeanPostProcessor"/>
<bean class="com.dpb.processor.MyInstantiationAwareBeanPostProcessor">bean>
<bean class="com.dpb.factoryprocessor.MyBeanFactoryPostProcessor"/>
beans>
@Test
public void test1() {
System.out.println("Spring容器开始加载....");
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = ac.getBean(User.class);
System.out.println("---------------"+user);
ac.registerShutdownHook();
System.out.println("Spring容器卸载完成....");
}
输出结果
Spring容器开始加载....
三月 04, 2019 11:14:38 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@707f7052: startup date [Mon Mar 04 23:14:38 CST 2019]; root of context hierarchy
三月 04, 2019 11:14:39 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
****** BeanFactoryPostProcessor 开始执行了
******* BeanFactoryPostProcessor 执行结束了
【--InstantiationAwareBeanPostProcessor----】postProcessBeforeInstantiation
构造方法被执行了...User 被实例化
【--InstantiationAwareBeanPostProcessor----】postProcessAfterInstantiation
【--InstantiationAwareBeanPostProcessor----】postProcessPropertyValues--->
《注入属性》注入name属性波波烤鸭
【BeanNameWare接口】setBeanName
【BeanFactoryAware接口】setBeanFactory
>>后置处理器 before方法:User [id=0, name=波波烤鸭, beanName=user] user
【---InstantiationAwareBeanPostProcessor---】 postProcessBeforeInitialization
初始化:【@PostConstruct】执行了...
初始化:《InitializingBean接口》afterPropertiesSet....
初始化:【init-method】方法执行了....
<<后置处理器after方法:User [id=0, name=波波烤鸭, beanName=user] user
【--InstantiationAwareBeanPostProcessor----】 postProcessAfterInitialization
---------------User [id=0, name=波波烤鸭, beanName=user]
Spring容器卸载完成....
三月 04, 2019 11:14:39 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@707f7052: startup date [Mon Mar 04 23:14:38 CST 2019]; root of context hierarchy
【@preDestory】执行了...
《DisposableBean接口》destroy ....
【destory-method】方法执行了....
~ 这就是Bean对象的生命周期了。有问题的欢迎留言