文档章节

springframework中的BeanPostProcessor(后处理bean)

zuodev
 zuodev
发布于 2016/04/19 22:50
字数 1094
阅读 13
收藏 0

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>






© 著作权归作者所有

zuodev
粉丝 0
博文 37
码字总数 18402
作品 0
静安
高级程序员
私信 提问
spring源码阅读笔记(一)

spring源码阅读笔记(一) 最近工作不忙,抽空阅读了下《spring源码深度剖析》,特此做一下记录。 先说下BeanFactoryPostProcessor接口和BeanPostProcessor接口,这两个接口都是spring 初始化...

纳兰清风
2015/12/20
256
0
Spring中的BeanPostProcessor接口

Spring提供了很多扩展接口,BeanPostProcessor接口和InstantiationAwareBeanPostProcessor接口就是其中两个。 BeanPostProcessor BeanPostProcessor接口作用是:如果我们需要在Spring容器完成...

真爱2015
2015/12/24
56
0
spring-ioc-native&容器扩展点

章节地址 7.6自定义一个bean的生命 (nature) 7.6.1 lifecycle callbacks(生命周期回调) 与容器的bean的生命周期管理相关,你可用实现spring的InitializingBean和DisposableBean接口.对于前者,...

流光韶逝
2016/08/15
11
0
spring --(12)bean的生命周期

springIOC容器可以管理bean的生命周期,管理过程: 1>通过构造器或工厂方法创建bean实例 2>给bean的属性设值 2.5>将bean的实例传送给bean的前置处理器,调用postProcessAfterInitialization(...

求是科技
2016/08/28
6
0
Spring service本类中方法调用另一个方法事务不生效问题

前些日子一朋友在需要在目标对象中进行自我调用,且需要实施相应的事务定义,且网上的一种通过BeanPostProcessor的解决方案是存在问题的。因此专门写此篇帖子分析why。 1、预备知识 aop概念请...

vshcxl
2016/12/01
329
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
今天
216
4
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
今天
10
0
计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
6
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
7
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部