CGLIB 实现代理对象
2015-05-31 16:03
232 查看
CGLIB 编程步骤:
cglib 执行intercept()的原理:
自定义类应该实现MethodInterceptor接口,,覆写 intercept()方法
Enhancer对象设其Callback对象(实际是Callbacks对象,一个数组,但我们经常只设一个)
这样当Enhancer对象建立代理对象的时候,就会在执行用户调用的方法前,先执行intercept()方法
常见的两种不同的实现MethodInterceptor接口的cglib编程
1.自定义类直接实现MethodInterceptor接口,覆写 intercept()方法
2.另一种方式,定义一个内部类,该类实现MethodInterceptor接口,覆写intercept()方法
注意 public Object intercept(Object
obj, Method method, Object[] aobj,MethodProxy methodproxy)方法的第一个参数obj有很大问题
intercept方法里的主要动作是执行invoke方法
有两种执行方法:
实际工作中发现,参数obj不态好用. 如果你想intercept()方法中调用对象执行一些方法的话,obj会出stackOverflow这样的异常
如下面的例子:
cglib 在 spring,hibernate中的应用
Hibernate主要是利用cglib生成pojo的子类并override get方法来实现lazy loading机制
Spring则是利用cglib来实现动态代理。
spring,hibernate同时支持proxy类动态代理和cglib,二者的区别
proxy动态代理只能对实现了接口的类生成代理,而不能针对类
CGLIB是针对类生成代理,主要是对用户类生成一个子类
spring 下缺省是支持proxy 动态代理,如何强制使用CGLIB生成代理?
spring 主要在两个地方使用代理
1. 加入库 | cglib库 cglib-2.2.jar asm库(cglib 需要asm库,如果没有加入asm的jar文件,就会报asm错误) asm-3.1.jar |
2. 定义CGLIB操作类 | package com.machome.cglibtest; import java.lang.reflect.Method; import com.machome.model.StuService; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGlibProxyFactory implements MethodInterceptor { private Object targetObject; public Object createProxyInstance(Object targetObject){ this.targetObject = targetObject; //传入用户类 Enhancer enhancer = new Enhancer(); //Enhancer是cglib的核心类 // 将用户类设为 Enhancer对象的superclass属性,,即设为 Enhancer对象的父类 enhancer.setSuperclass(this.targetObject.getClass()); // 设 Enhancer对象的Callbacks属性,要求必须是Callback接口类型 enhancer.setCallback(this); return enhancer.create(); //生成代理对象 } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { StuService bean = (StuService)this.targetObject; Object result = null; if(!arg1.getName().equals("save")&&(bean.findAll().size()==0)) { // 如果方法名不是save(即是get,update,delete方法),而同时实例的列表为空,就不执行方法,而是告警 System.out.println("list is null,method is stoped"); }else{ //执行代理方法,传入实例和方法参数 result = arg3.invoke(targetObject, arg2); } return result; } } |
3.测试代码 | 测试代码: CGlibProxyFactory factory = new CGlibProxyFactory(); StuService bean = (StuService)factory.createProxyInstance( new StuService()); List<Stu> stuList = bean.findAll(); if(stuList!=null){ for(Stu temp:stuList) System.out.println(temp.getId()+":"+temp.getName()); System.out.println("finished"); 执行结果: list is null,method is stoped //bean.findAll()下边的语句都没执行) |
自定义类应该实现MethodInterceptor接口,,覆写 intercept()方法
public interface MethodInterceptor extends Callback { public abstract Object intercept(Object obj, Method method, Object aobj[], MethodProxy methodproxy) throws Throwable; } |
enhancer.setCallback(Callback callback); |
常见的两种不同的实现MethodInterceptor接口的cglib编程
1.自定义类直接实现MethodInterceptor接口,覆写 intercept()方法
public class CGlibProxyFactory implements MethodInterceptor { public Object createProxyInstance(Object targetObject){ ... enhancer.setCallback(this); ... } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { ... } } |
public class CGlibProxyFactory1 { public Object createProxyInstance(Object targetObject){ ... enhancer.setCallback(new MethodInterceptorImpl()); ... } private class MethodInterceptorImpl implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] aobj, MethodProxy methodproxy) throws Throwable { ... } } } |
obj, Method method, Object[] aobj,MethodProxy methodproxy)方法的第一个参数obj有很大问题
intercept方法里的主要动作是执行invoke方法
有两种执行方法:
法1: | 将参数obj传入invokeSuper()方法: return methodproxy.invokeSuper(obj, aobj); obj应该是传入Enhancer 对象的用户对象 (即上边enhancer.setSuperclass(this.targetObject.getClass())) |
法2: | 或者将传入Enhancer对象前的原始用户对象传入invoke()方法: return methodproxy.invoke(targetObject, aobj); |
如下面的例子:
public Object intercept(Object obj, Method method, Object[] aobj, MethodProxy methodproxy) throws Throwable { StuService bean = (StuService)obj; Object result = null; if(!method.getName().equals("save")&&(bean.findAll().size()==0)) { // 如果方法名不是save,而实例的列表为空,就不执行方法,而是告警 System.out.println("list is null,method is stoped"); }else{ result = methodproxy.invokeSuper(obj, aobj); } return result; } |
执行时会出线面的异常: Exception in thread "main" java.lang.StackOverflowError |
改成下面就好了: public Object intercept(Object obj, Method method, Object[] aobj, MethodProxy methodproxy) throws Throwable { StuService bean = (StuService)this.targetObject; //从外部传入的原始用户实例 Object result = null; if(!method.getName().equals("save")&&(bean.findAll().size()==0)) { // 如果方法名不是save,而实例的列表为空,就不执行方法,而是告警 System.out.println("list is null,method is stoped"); }else{ result = methodproxy.invoke(targetObject, aobj); } return result; } |
Hibernate主要是利用cglib生成pojo的子类并override get方法来实现lazy loading机制
Spring则是利用cglib来实现动态代理。
spring,hibernate同时支持proxy类动态代理和cglib,二者的区别
proxy动态代理只能对实现了接口的类生成代理,而不能针对类
CGLIB是针对类生成代理,主要是对用户类生成一个子类
spring 下缺省是支持proxy 动态代理,如何强制使用CGLIB生成代理?
spring 主要在两个地方使用代理
AOP: <aop:aspectj-autoproxy proxy-target-class="true"/> |
Transaction: <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/> |
相关文章推荐
- iOS编程——隐藏和封装
- 表变量
- Maven: Maven Antrun Plugin configuration to copy package from target to basedir and rename it
- 字符串的长度
- 算法导论--10.3-4 多数组表示双向链表(紧凑)
- C语言笔记(一)
- 织梦PHP站一直被黑客挂木马的解决办法
- 机房收费系统——UML图感想
- 愚人小游戏
- signal raise alarm用法
- 红黑树:自平衡的二叉查找树
- 合并排序
- 让IE6 IE7 IE8 IE9 IE10 IE11支持Bootstrap的解决方法
- 逆天的 GRUB
- Python之学习笔记(函数)
- Android 继承DialogFragment弹出dialog对话框
- redis集群&主从部署
- Mapreduce的排序、全排序以及二次排序
- JAVA设计模式--Strategy
- 看懂别人的代码,和自己能写代码是两回事