springframework中的BeanPostProcessor(后处理bean)

原创
2016/04/19 22:50
阅读数 62

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>






展开阅读全文
打赏
1
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
1
分享
返回顶部
顶部