Spring Bean 后置处理器BeanPostProcessor
Spring 提供一种机制,只要实现此接口BeanPostProcessor,并将实现类提供给spring容器,spring容器将自动执行,在初始化方法前执行before(),在初始化方法后执行after()
可以配置多个 BeanPostProcessor 接口,通过设置 BeanPostProcessor 实现的 Ordered 接口提供的 order 属性来控制这些 BeanPostProcessor 接口的执行顺序。
ApplicationContext 会自动检测由 BeanPostProcessor 接口的实现定义的 bean,注册这些 bean 为后置处理器,然后通过在容器中创建 bean,在适当的时候调用它。
-
Factory hook(勾子) that allows for custom modification of new bean instances, e.g. checking for marker interfaces or wrapping them with proxies.
-
spring提供工厂勾子,用于修改实例对象,可以生成代理对象,是AOP底层。
模拟
A a =new A();
a = B.before(a) --> 将a的实例对象传递给后处理bean,可以生成代理对象并返回。
a.init();
a = B.after(a);
a.addUser(); //生成代理对象,目的在目标方法前后执行(例如:开启事务、提交事务)
a.destroy()
BeanPostProcessor实现类代码演示
- BeanPostProcessor实现类1,同时实现getOrder方法来控制这些 执行顺序
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
public class PostProcessor implements BeanPostProcessor,Ordered {
//可以在初始化 bean 的之前和之后实现更复杂的逻辑。
//在Init-method的前后执行
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization1:" + beanName);
((InitHelloWorld)bean).getMessage();
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization1:" + beanName);
((InitHelloWorld)bean).getMessage();
return bean;
}
@Override
public int getOrder() {
return 0;
}
}
- BeanPostProcessor实现类2
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
public class PostProcessor2 implements BeanPostProcessor,Ordered {
//可以在初始化 bean 的之前和之后实现更复杂的逻辑。
//在Init-method的前后执行
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization2:" + beanName);
((InitHelloWorld)bean).getMessage();
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization2:" + beanName);
((InitHelloWorld)bean).getMessage();
return bean;
}
@Override
public int getOrder() {
return 1;
}
}
- 配置
<?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="initHelloWorld" class="com.cc.study.lifecycle.InitHelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"></property>
</bean>
<bean id="postProcessor" class="com.cc.study.lifecycle.PostProcessor"></bean>
<bean id="postProcessor2" class="com.cc.study.lifecycle.PostProcessor2"></bean>
</beans>
- InitHelloWorld
public class InitHelloWorld{
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
public void init(){
System.out.println("Bean is going through init.");
}
public void destroy(){
System.out.println("Bean will destroy now.");
}
}
- 测试
@Test
public void demo(){
String xmlPath = "lifecycle2.xml";
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
InitHelloWorld initHelloWorld = applicationContext.getBean("initHelloWorld",InitHelloWorld.class);
initHelloWorld.getMessage();
applicationContext.registerShutdownHook();
}
BeanPostProcessor生成代理对象
- MyBeanPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("前方法 : " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("后方法 : " + beanName);
// bean 目标对象
// 生成 jdk 代理
return Proxy.newProxyInstance(
MyBeanPostProcessor.class.getClassLoader(),
bean.getClass().getInterfaces(),
new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("------开启事务");
System.out.println("调用方法:" + method.getName());
//执行目标方法
Object obj = method.invoke(bean, args);
System.out.println("------提交事务");
return obj;
}});
}
}
- 配置
<?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">
<!-- 创建dao实例 -->
<bean id="bookDaoId" class="com.cc.study.di.BookDaoImpl"></bean>
<!-- 将后处理的实现类注册给spring -->
<bean id="myBeanPostProcessor" class="com.cc.study.lifecycle.MyBeanPostProcessor"></bean>
</beans>
- BookDaoImpl
public class BookDaoImpl implements BookDao {
@Override
public void addBook() {
System.out.println("di add book");
}
}
- 测试
@Test
public void demo(){
String xmlPath = "lifecycle3.xml";
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
BookDao bookDao = applicationContext.getBean("bookDaoId",BookDao.class);
bookDao.addBook();
}
注意:
问题1:后处理bean作用某一个目标类,还是所有目标类?
所有
问题2:如何只作用一个?
通过“参数2”beanName进行控制