日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CGLIB 实现代理对象API

發布時間:2023/12/3 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。