CGLIB 实现代理对象API
生活随笔
收集整理的這篇文章主要介紹了
CGLIB 实现代理对象API
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉載自?CGLIB 實現代理對象API
| 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()下邊的語句都沒執行) |
cglib 執行intercept()的原理:
- 自定義類應該實現MethodInterceptor接口,,覆寫 intercept()方法
| public interface MethodInterceptor extends Callback { ??? public abstract Object intercept(Object obj, Method method, Object aobj[], MethodProxy methodproxy) ??????? throws Throwable; } |
- Enhancer對象設其Callback對象(實際是Callbacks對象,一個數組,但我們經常只設一個) ???
| ?enhancer.setCallback(Callback callback); |
- 這樣當Enhancer對象建立代理對象的時候,就會在執行用戶調用的方法前,先執行intercept()方法
常見的兩種不同的實現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 { ??? ??? ??? ... ??? ??? ??? }??? } |
- 2.另一種方式,定義一個內部類,該類實現MethodInterceptor接口,覆寫intercept()方法
| 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 { ??? ??? ??? ??? ... ??? ??? ??? ??? } ?? } ?}? |
注意 public Object intercept(Object 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); |
實際工作中發現,參數obj不態好用. 如果你想intercept()方法中調用對象執行一些方法的話,obj會出stackOverflow這樣的異常
如下面的例子:
| ??? 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; } |
cglib 在 spring,hibernate中的應用
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"/> |
| 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()下邊的語句都沒執行) |
cglib 執行intercept()的原理:
- 自定義類應該實現MethodInterceptor接口,,覆寫 intercept()方法
| public interface MethodInterceptor extends Callback { ??? public abstract Object intercept(Object obj, Method method, Object aobj[], MethodProxy methodproxy) ??????? throws Throwable; } |
- Enhancer對象設其Callback對象(實際是Callbacks對象,一個數組,但我們經常只設一個) ???
| ?enhancer.setCallback(Callback callback); |
- 這樣當Enhancer對象建立代理對象的時候,就會在執行用戶調用的方法前,先執行intercept()方法
常見的兩種不同的實現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 { ??? ??? ??? ... ??? ??? ??? }??? } |
- 2.另一種方式,定義一個內部類,該類實現MethodInterceptor接口,覆寫intercept()方法
| 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 { ??? ??? ??? ??? ... ??? ??? ??? ??? } ?? } ?}? |
注意 public Object intercept(Object 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); |
實際工作中發現,參數obj不態好用. 如果你想intercept()方法中調用對象執行一些方法的話,obj會出stackOverflow這樣的異常
如下面的例子:
| ??? 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; } |
cglib 在 spring,hibernate中的應用
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"/> |
總結
以上是生活随笔為你收集整理的CGLIB 实现代理对象API的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 看看亚马逊那些笑死人的评价亚马逊怎么看评
- 下一篇: 一款开源免费的动态桌面壁纸软件一款开源免