spring提供后处理bean -- BeanPostProcessor接口
文档说明:Factory hook(勾子) that allows for custom modification of new bean instances, e.g. checking for marker interfaces or wrapping them with proxies.
即spring提供勾子程序,用于运行时,修改spring创建bean实例,可以提供代理对象。用的是面向切面编程思想(aop).
这里的后处理bean的处理效果和spring aop(spring 面向切面编程)的效果一样.
那么后处理bean和spring aop区别?
后处理bean是spring基础核心部分,而spring aop编程是基于spring核心部分和aop联盟的思想的编程.
看看后处理bean与目标方法的执行过程
package com.itheima.f_lifecycle_beanpost;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;[由全限定类名可知,该对象是spring核心对象,而不是引入对象]
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("before BeanPostProcessor");
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("before BeanPostProcessor --- before target method");
//执行目标类的方法
Object obj = method.invoke(bean, args);
System.out.println("before BeanPostProcessor --- after target method");
return obj;
}
});
}
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("after BeanPostProcessor");
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("after BeanPostProcessor --- before target method");
//执行目标类的方法
Object obj = method.invoke(bean, args);
System.out.println("after BeanPostProcessor --- after target method");
return obj;
}
});
}
}
运行结果:
before BeanPostProcessor
after BeanPostProcessor
after BeanPostProcessor --- before target method
before BeanPostProcessor --- before target method
target method
before BeanPostProcessor --- after target method
after BeanPostProcessor --- after target method
由运行结果可知,程序会同时进入前后BeanPostProcessor,在环绕目标(around)执行相应程序
-----------------------------------------------------------------------------------------------------------------------------------------
整个目录工程如下, 完整代码在文章最后.
细节分析.
看看BeanPostProcessor 接口
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
我们让MyBeanPostProcessor 继承BeanPostProcessor
package com.itheima.f_lifecycle_beanpost;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return null;
}
运行如下测试代码:
package com.itheima.f_lifecycle_beanpost;
import org.junit.Test;
public class TestBeanPost {
@Test
public void demo01() throws Exception{
//spring 配置
String xmlPath = "com/itheima/f_lifecycle_beanpost/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
CategoryService categoryService = (CategoryService) applicationContext.getBean("categoryServiceId");
categoryService.addCategory();
}
}
运行结果: 会报空指针异常.
将返回值两个都改为bean.
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
这时候可以正常运行.即真实对象会被传入自定义的后处理bean方法中.
在postProcessAfterInitialization方法中加入动态代理
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("后");
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("目标方法前 -- 开启事务");
//执行目标类的方法
Object obj = method.invoke(bean, args);
System.out.println("目标方法后 -- 提交事务");
return obj;
}
});
}
运行结果:
目标方法前 -- 开启事务
target method
目标方法后 -- 提交事务
这里的Object obj = method.invoke(bean, args); 返回值obj是null,因为目标方法返回值类型是void.
--------------------------------------------------------------------------------------------------------------------------------------
全部代码
CategoryServcie
package com.itheima.f_lifecycle_beanpost;
public interface CategoryService {
public void addCategory();
}
CategoryServiceImpl
package com.itheima.f_lifecycle_beanpost;
public class CategoryServiceImpl implements CategoryService {
@Override
public void addCategory() {
System.out.println("target method");
}
public void myInit(){
System.out.println("初始化");
}
}
MyBeanPostProcessor
package com.itheima.f_lifecycle_beanpost;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
// @Override
// public Object postProcessBeforeInitialization(Object bean, String beanName)
// throws BeansException {
// return bean;
// }
//
// @Override
// public Object postProcessAfterInitialization(Object bean, String beanName)
// throws BeansException {
// return bean;
// }
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("before BeanPostProcessor");
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("before BeanPostProcessor --- before target method");
//执行目标类的方法
Object obj = method.invoke(bean, args);
System.out.println("before BeanPostProcessor --- after target method");
return null;
}
});
}
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
System.out.println("after BeanPostProcessor");
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("after BeanPostProcessor --- before target method");
//执行目标类的方法
Object obj = method.invoke(bean, args);
System.out.println("after BeanPostProcessor --- after target method");
return obj;
}
});
}
}
TestBeanPost
package com.itheima.f_lifecycle_beanpost;
import org.junit.Test;
public class TestBeanPost {
@Test
public void demo01() throws Exception{
//spring 配置
String xmlPath = "com/itheima/f_lifecycle_beanpost/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
CategoryService categoryService = (CategoryService) applicationContext.getBean("categoryServiceId");
categoryService.addCategory();
}
}
beans.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="categoryServiceId" class="com.itheima.f_lifecycle_beanpost.CategoryServiceImpl" />
<!-- <bean id="categoryServiceId" class="com.itheima.f_lifecycle_beanpost.CategoryServiceImpl" -->
<!-- init-method="myInit" ></bean> -->
<!-- 配置后处理bean,当前配置文件中的其他所有的bean都将生效 -->
<bean class="com.itheima.f_lifecycle_beanpost.MyBeanPostProcessor"></bean>
</beans>