基础概念:
1、实例化—-实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中
2、初始化—-初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性
sprig beanPostProcessor 后置处理器主要用于对在对象初始化之前或者在对象初始化之后在这期间可以对对象做一些其他事情,比如创建代理,实现一些操作,下面是简单的实现:
首先搭建起spring环境
xml文件如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- bean 配置 -->
<bean id="oneBean" class="com.gysoft.spring.beanpost.OneBean" lazy-init="true" >
<!-- 构造方法 -->
<constructor-arg name="name" value="配置文件赋予的名字"/>
</bean>
<!-- bean后处理器 类似于filter -->
<bean id="beanProcessor" class="com.gysoft.spring.beanpost.MyBeanPost"/>
<!-- 包扫描 -->
<!-- <context:component-scan base-package="myspring"/> -->
</beans>
创建一个bean
package com.gysoft.spring.beanpost;
import lombok.Data;
/**
* @Description
* @Author DJZ-WWS
* @Date 2019/5/6 20:52
*/
@Data
public class OneBean {
private String name;
private int age;
private String email;
public OneBean() {
System.out.println("调用无参构造器");
}
public OneBean(String name) {
this.name = name;
System.out.println("调用有参构造器");
}
}
创建后置处理器
package com.gysoft.spring.beanpost;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @Description
* @Author DJZ-WWS
* @Date 2019/5/6 20:49
*/
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof OneBean){
System.out.println("赋值之前"+bean);
((OneBean) bean).setName("哈哈");
System.out.println(bean);
}
System.out.println("bean 的后置处理器 postProcessBeforeInitialization 方法 bean 初始化之前");
//这里一定要返回bean,不能返回null
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof OneBean){
((OneBean) bean).setAge(12);
}
System.out.println("postProcessAfterInitialization方法里"+bean);
System.out.println("bean的后置处理器 postProcessAfterInitialization方法 bean初始化后调用");
return bean;
}
}
对两个方法进行简单说明,
postProcessBeforeInitialization这个方法知名知其意,BeforeInitialization初始化之前,这个方法在初始化方法之前执行,
postProcessAfterInitialization这个方法在初始化之后执行。(初始化方法有三种配置方式,通过注解@PostConstrut., @PreDestroy,通过xml指定bean init方法)。
这里需要注意的地方,两个方法的返回值都是实例对象,默认实现后是返回的是null,如果返回的是null那么通过getBean的方式获得对象也一定定是null,因为是同一个对象。
创建测试类
package com.gysoft.spring.beanpost;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Description
* @Author DJZ-WWS
* @Date 2019/5/6 21:02
*/
public class BeanPostTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext app=new ClassPathXmlApplicationContext("beanpost.xml");
OneBean oneBean = app.getBean("oneBean", OneBean.class);
System.out.println(oneBean);
}
}
说明:bean生命周期相关的东西和加载方式有很大关系,对象默认为非懒加载,当对象被声明为懒加载的时候,bean声明周期相关的接口在对象被调用的时候才开始执行他的初始化相关接口,即容器加载完毕和对象被调用两种时机。
为了测试此结论可以做一下验证:
在getBean那一行打上断点进行调试,针对这两种情况,控制台会有不一样的情况。
打印结果如下:
有参构造器
赋值之前OneBean(name=配置文件赋予的名字, age=0, email=null)
OneBean(name=哈哈, age=0, email=null)
bean 的后置处理器 postProcessBeforeInitialization 方法 bean 实例化之前
postProcessAfterInitialization方法里OneBean(name=哈哈, age=12, email=null)
bean的后置处理器 postProcessAfterInitialization方法 bean实例化以后调用