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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

CGLIB代理到底是个什么东西?这是一篇最全的CGLIB大全

發布時間:2025/3/19 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CGLIB代理到底是个什么东西?这是一篇最全的CGLIB大全 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

?

0 概述

0.1 CGLIB包結構

1 使用CGLIB實現動態代理

1.1 CGLIB代理相關的類

1.2 CGLIB動態代理的基本原理

1.3 使用MethodInterceptor接口實現方法回調

1.3.1 實現MethodInterceptor接口

1.4 使用CGLIB代理最核心類Enhancer生成代理對象

1.5 使用CGLIB繼進行動態代理示例

2 回調過濾器CallbackFilter

3 CGLIB對Mixin的支持

4 CGLIB用來對象之間拷貝屬性

5 使用CGLIB動態生成Bean


0 概述

CGLIB基于ASM實現。提供比反射更為強大的動態特性。使用CGLIB可以非常方便的實現的動態代理。

?

0.1 CGLIB包結構

  • net.sf.cglib.core?? ?底層字節碼處理類。

  • net.sf.cglib.transform?? ?該包中的類用于class文件運行時轉換或編譯時轉換。

  • net.sf.cglib.proxy?? ?該包中的類用于創建代理和方法攔截。

  • net.sf.cglib.reflect?? ?該包中的類用于快速反射,并提供了C#風格的委托。

  • net.sf.cglib.util?? ?集合排序工具類。

  • net.sf.cglib.beans?? ?JavaBean工具類。

?

?

?

1 使用CGLIB實現動態代理

1.1 CGLIB代理相關的類

  • net.sf.cglib.proxy.Enhancer????主要的增強類。
  • net.sf.cglib.proxy.MethodInterceptor????主要的方法攔截類,它是Callback接口的子接口,需要用戶實現。
  • net.sf.cglib.proxy.MethodProxy????JDK的java.lang.reflect.Method類的代理類,可以方便的實現對源對象方法的調用。

cglib是通過動態的生成一個子類去覆蓋所要代理類的非final方法,并設置好callback,則原有類的每個方法調用就會轉變成調用用戶定義的攔截方法(interceptors)。

CGLIB代理相關的常用API如下圖所示:

?

net.sf.cglib.proxy.Callback接口在CGLIB包中是一個重要的接口,所有被net.sf.cglib.proxy.Enhancer類調用的回調(callback)接口都要繼承這個接口。

net.sf.cglib.proxy.MethodInterceptor能夠滿足任何的攔截(interception?)需要。對有些情況下可能過度。為了簡化和提高性能,CGLIB包提供了一些專門的回調(callback)類型:

  • net.sf.cglib.proxy.FixedValue?為提高性能,FixedValue回調對強制某一特別方法返回固定值是有用的。
  • net.sf.cglib.proxy.NoOp?NoOp回調把對方法調用直接委派到這個方法在父類中的實現。
  • net.sf.cglib.proxy.LazyLoader?當實際的對象需要延遲裝載時,可以使用LazyLoader回調。一旦實際對象被裝載,它將被每一個調用代理對象的方法使用。
  • net.sf.cglib.proxy.Dispatcher?Dispathcer回調和LazyLoader回調有相同的特點,不同的是,當代理方法被調用時,裝載對象的方法也總要被調用。
  • net.sf.cglib.proxy.ProxyRefDispatcher?ProxyRefDispatcher回調和Dispatcher一樣,不同的是,它可以把代理對象作為裝載對象方法的一個參數傳遞。

?

?

1.2 CGLIB動態代理的基本原理

CGLIB動態代理的原理就是用Enhancer生成一個原有類的子類,并且設置好callback到proxy, 則原有類的每個方法調用都會轉為調用實現了MethodInterceptor接口的proxy的intercept() 函數,如圖

在intercept()函數里,除執行代理類的原因方法,在原有方法前后加入其他需要實現的過程,改變原有方法的參數值,即可以實現對原有類的代理了。這似于AOP中的around advice。

?

?

1.3 使用MethodInterceptor接口實現方法回調

當對代理中所有方法的調用時,都會轉向MethodInterceptor類型的攔截(intercept)方法,在攔截方法中再調用底層對象相應的方法。下面我們舉個例子,假設你想對目標對象的所有方法調用進行權限的檢查,如果沒有經過授權,就拋出一個運行時的異常。

net.sf.cglib.proxy.MethodInterceptor接口是最通用的回調(callback)類型,它經常被基于代理的AOP用?來實現攔截(intercept)方法的調用。

MethodInterceptor接口只定義了一個方法:

public?Object?intercept(Object?object,?java.lang.reflect.Method?method,?Object[]?args,?MethodProxy?proxy)?throws?Throwable;

參數Object?object是被代理對象,不會出現死循環的問題。

參數java.lang.reflect.Method?method是java.lang.reflect.Method類型的被攔截方法。

參數Object[]?args是被被攔截方法的參數。

參數MethodProxy?proxy是CGLIB提供的MethodProxy?類型的被攔截方法。

注意:

1、若原方法的參數存在基本類型,則對于第三個參數Object[]?args會被轉化成類的類型。如原方法的存在一個參數為int,則在intercept方法中,對應的會存在一個Integer類型的參數。

2、若原方法為final方法,則MethodInterceptor接口無法攔截該方法。

?

1.3.1 實現MethodInterceptor接口

class?MethodInterceptorImpl?implements?MethodInterceptor {

? ? @Override????

? ??public?Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)?throwsThrowable {

? ??? ??System.out.println("Before invoke "?+ method);

? ??? ??Object result = proxy.invokeSuper(obj, args);

? ??? ??System.out.println("After invoke"?+ method);

? ??? ??return?result;

? ??}

}

Object result=proxy.invokeSuper(o,args);?表示調用原始類的被攔截到的方法。這個方法的前后添加需要的過程。在這個方法中,我們可以在調用原方法之前或之后注入自己的代碼。?

由于性能的原因,對原始方法的調用使用CGLIB的net.sf.cglib.proxy.MethodProxy對象,而不是反射中一般使用java.lang.reflect.Method對象。

?

?

1.4 使用CGLIB代理最核心類Enhancer生成代理對象

net.sf.cglib.proxy.Enhancer中有幾個常用的方法:

  • void?setSuperclass(java.lang.Class superclass)?設置產生的代理對象的父類。
  • void?setCallback(Callback callback)?設置CallBack接口的實例。
  • void?setCallbacks(Callback[] callbacks)?設置多個CallBack接口的實例。
  • void?setCallbackFilter(CallbackFilter filter)?設置方法回調過濾器。
  • Object?create()?使用默認無參數的構造函數創建目標對象。
  • Object?create(Class[],?Object[])?使用有參數的構造函數創建目標對象。參數Class[] 定義了參數的類型,第二個Object[]是參數的值。

注意:在參數中,基本類型應被轉化成類的類型。

基本代碼:

public?Object createProxy(Class targetClass) {

? ??Enhancer enhancer =?new?Enhancer();

? ??enhancer.setSuperclass(targetClass);

? ??enhancer.setCallback(new?MethodInterceptorImpl ());

? ??return?enhancer.create();

}

createProxy方法返回值是targetClass的一個實例的代理。

?

?

1.5 使用CGLIB繼進行動態代理示例

例1:使用CGLIB生成代理的基本使用。

import?java.lang.reflect.Method;

?

import?net.sf.cglib.proxy.Enhancer;

import?net.sf.cglib.proxy.MethodInterceptor;

import?net.sf.cglib.proxy.MethodProxy;

?

public?class?TestMain {

????public?static?void?main(String[] args) {

????????Enhancer enhancer =?new?Enhancer();

????????enhancer.setSuperclass(Cglib.class);

????????enhancer.setCallback(new?HelloProxy());

????????Cglib cglibProxy = (Cglib)enhancer.create();

????????cglibProxy.cglib();

????}

}

?

class?Cglib{

????public?void?cglib(){

????????System.out.println("CGLIB");

????}

}

?

class?HelloProxy?implements?MethodInterceptor{

????@Override

????public?Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)?throwsThrowable {

????????System.out.println("Hello");

????????Object object = proxy.invokeSuper(obj, args);

????????System.out.println("Powerful!");

????????return?object;

????}

}

?

輸出內容:

Hello

CGLIB

Powerful!

?

?

例2:使用CGLIB創建一個Dao工廠,并展示一些基本特性。

public?interface?Dao {

????void?add(Object o);

????void?add(int?i);

????void?add(String?s);

}

?

public?class?DaoImpl?implements?Dao {

????@Override

????public?void?add(Object o) {

????????System.out.println("add(Object o)");

????}

?

????@Override

????public?void?add(int?i) {

????????System.out.println("add(int i)");

????}

?

????public?final?void?add(String s) {

????????System.out.println("add(String s)");

????}

}

?

?

public?class?Proxy?implements?MethodInterceptor {

????@Override

????public?Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)?throwsThrowable {

????????System.out.println("攔截前...");

?

????????// 輸出參數類型

????????for?(Object arg : args) {

????????????System.out.print(arg.getClass() +?";");

????????}

????????Object result = proxy.invokeSuper(obj, args);

?

????????System.out.println("攔截后...");

????????return?result;

????}

}

?

public?class?DaoFactory {

????public?static?Dao create() {

????????Enhancer enhancer =?new?Enhancer();

????????enhancer.setSuperclass(DaoImpl.class);

????????enhancer.setCallback(new?Proxy());

????????Dao dao = (Dao) enhancer.create();

????????return?dao;

????}

}

?

public?class?TestMain {

????public?static?void?main(String[] args) {

????????Dao dao = DaoFactory.create();

????????dao.add(new?Object());

????????dao.add(1);

????????dao.add("1");

????}

}

?

輸出內容:

攔截前...

class java.lang.Object;add(Object o)

攔截后...

攔截前...

class java.lang.Integer;add(int i)

攔截后...

add(String s)

?

?

?

2 回調過濾器CallbackFilter

net.sf.cglib.proxy.CallbackFilter有選擇的對一些方法使用回調。

CallbackFilter可以實現不同的方法使用不同的回調方法。所以CallbackFilter稱為"回調選擇器"更合適一些。

CallbackFilter中的accept方法,根據不同的method返回不同的值i,這個值是在callbacks中callback對象的序號,就是調用了callbacks[i]。

?

import?java.lang.reflect.Method;

?

import?net.sf.cglib.proxy.Callback;

import?net.sf.cglib.proxy.CallbackFilter;

import?net.sf.cglib.proxy.Enhancer;

import?net.sf.cglib.proxy.MethodInterceptor;

import?net.sf.cglib.proxy.MethodProxy;

import?net.sf.cglib.proxy.NoOp;

?

public?class?CallbackFilterDemo {

????public?static?void?main(String[] args) {

????????// 回調實例數組

????????Callback[] callbacks =?new?Callback[] {?new?MethodInterceptorImpl(), NoOp.INSTANCE?};

?

????????// 使用enhancer,設置相關參數。

????????Enhancer enhancer =?new?Enhancer();

????????enhancer.setSuperclass(User.class);

????????enhancer.setCallbacks(callbacks);

????????enhancer.setCallbackFilter(new?CallbackFilterImpl());

?

????????// 產生代理對象

????????User proxyUser = (User) enhancer.create();

?

????????proxyUser.pay();?// 買

????????proxyUser.eat();?// 吃

????}

?

????/**

???? * 回調過濾器類。

???? */

????private?static?class?CallbackFilterImpl?implements?CallbackFilter {

?

????????@Override

????????public?int?accept(Method method) {

????????????String methodName = method.getName();

????????????if?("eat".equals(methodName)) {

????????????????return?1;?// eat()方法使用callbacks[1]對象攔截。

????????????}?else?if?("pay".equals(methodName)) {

????????????????return?0;?// pay()方法使用callbacks[0]對象攔截。

????????????}

????????????return?0;

????????}

????}

?

????/**

???? * 自定義回調類。

???? */

????private?static?class?MethodInterceptorImpl?implements?MethodInterceptor {

?

????????@Override

????????public?Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)throws?Throwable {

????????????System.out.println("Before invoke "?+ method);

????????????Object result = proxy.invokeSuper(obj, args);?// 原方法調用。

????????????System.out.println("After invoke"?+ method);

????????????return?result;

????????}

????}

}

?

class?User {

????public?void?pay() {

????????System.out.println("買東西");

????}

?

????public?void?eat() {

????????System.out.println("吃東西");

????}

}

?

輸出結果:

Before invoke public void sjq.cglib.filter.User.pay()

pay()

After invokepublic void sjq.cglib.filter.User.pay()

eat()

?

?

?

3 CGLIB對Mixin的支持

CGLIB的代理包net.sf.cglib.proxy.Mixin類提供對Minix編程的支持。Minix允許多個對象綁定到一個單個的大對象上。在代理中對方法的調用委托到下面相應的對象中。?這是一種將多個接口混合在一起的方式,?實現了多個接口。

Minix是一種多繼承的替代方案,?很大程度上解決了多繼承的很多問題,?實現和理解起來都比較容易。

import?net.sf.cglib.proxy.Mixin;

?

public?class?MixinDemo {

????public?static?void?main(String[] args) {

????????//接口數組

????????Class<?>[] interfaces =?new?Class[] { MyInterfaceA.class, MyInterfaceB.class?};

???????? ?

????????//實例對象數組

????????Object[] delegates =?new?Object[] {?new?MyInterfaceAImpl(),?new?MyInterfaceBImpl() };

???????? ?

????????//Minix組合為o對象。

????????Object o = Mixin.create(interfaces, delegates);

???????? ?

????????MyInterfaceA a = (MyInterfaceA) o;

????????a.methodA();

???????? ?

????????MyInterfaceB b = (MyInterfaceB) o;

????????b.methodB();

???????? ?

????????System.out.println("\r\n 輸出Mixin對象的結構...");

????????Class clazz = o.getClass();

????????Method[] methods = clazz.getDeclaredMethods();

????????for?(int?i = 0; i < methods.length; i++) {

????????????System.out.println(methods[i].getName());

????????}

????????System.out.println(clazz);

????}

}

?

interface?MyInterfaceA {

????public?void?methodA();

}

?

interface?MyInterfaceB {

????public?void?methodB();

}

?

class?MyInterfaceAImpl?implements?MyInterfaceA {

????@Override

????public?void?methodA() {

????????System.out.println("MyInterfaceAImpl.methodA()");

????}

}

?

class?MyInterfaceBImpl?implements?MyInterfaceB {

????@Override

????public?void?methodB() {

????????System.out.println("MyInterfaceBImpl.methodB()");

????}

}

?

輸出結果:

MyInterfaceAImpl.methodA()

MyInterfaceBImpl.methodB()

?

輸出Mixin對象的結構...

methodA

methodB

newInstance

class sjq.cglib.mixin.MyInterfaceA

MixinByCGLIBMixinByCGLIB

d1f6261a

?

?

?

4 CGLIB用來對象之間拷貝屬性

package?sjq.cglib.bean.copy;

?

import?net.sf.cglib.beans.BeanCopier;

?

public?class?PropertyCopyDemo {

????public?static?void?main(String[] args) {

????????//兩個對象

????????Other other =?new?Other("test",?"1234");

????????Myth myth =?new?Myth();

?

????????System.out.println(other);

????????System.out.println(myth);

?

????????//構建BeanCopier,并copy對象的屬性值。

????????BeanCopier copier = BeanCopier.create(Other.class, Myth.class,?false);

????????copier.copy(other, myth,?null);

?

????????System.out.println(other);

????????System.out.println(myth);

????}

}

?

class?Other {

????private?String?username;

????private?String?password;

????private?int?age;

?

????public?String getUsername() {

????????return?username;

????}

?

????public?void?setUsername(String username) {

????????this.username?= username;

????}

?

????public?String getPassword() {

????????return?password;

????}

?

????public?void?setPassword(String password) {

????????this.password?= password;

????}

?

????public?Other(String username, String password) {

????????super();

????????this.username?= username;

????????this.password?= password;

????}

?

????@Override

????public?String toString() {

????????return?"Other: "?+?username?+?", "?+?password?+?", "?+?age;

????}

?

????public?int?getAge() {

????????return?age;

????}

?

????public?void?setAge(int?age) {

????????this.age?= age;

????}

}

?

class?Myth {

????private?String?username;

????private?String?password;

????private?String?remark;

?

????public?String getUsername() {

????????return?username;

????}

?

????public?void?setUsername(String username) {

????????this.username?= username;

????}

?

????public?String getPassword() {

????????return?password;

????}

?

????public?void?setPassword(String password) {

????????this.password?= password;

????}

?

????@Override

????public?String toString() {

????????return?"Myth: "?+?username?+?", "?+?password?+?", "?+?remark;

????}

?

????public?void?setRemark(String remark) {

????????this.remark?= remark;

????}

?

????public?String getRemark() {

????????return?remark;

????}

}

?

運行結果如下:

Other: test, 1234, 0

Myth: null, null, null

Other: test, 1234, 0

Myth: test, 1234, null

?

?

?

5 使用CGLIB動態生成Bean

import?java.util.Iterator;

import?java.util.Map;

import?java.util.Set;

import?net.sf.cglib.beans.BeanGenerator;

import?net.sf.cglib.beans.BeanMap;

?

/**

*動態實體bean

*/

public?class?CglibBean {

????/**

???? * 實體Object

???? */

????public?Object?object?=?null;

????

????/**

???? * 屬性map

???? */

????public?BeanMap?beanMap?=?null;

?

????public?CglibBean() {

????????super();

????}

?

????@SuppressWarnings("unchecked")

????public?CglibBean(Map<String, Class> propertyMap) {

????????this.object?= generateBean(propertyMap);

????????this.beanMap?= BeanMap.create(this.object);

????}

?

????/**

???? * 給bean屬性賦值

???? *?@param?property屬性名

???? *?@param?value值

???? */

????public?void?setValue(String property, Object value) {

????????beanMap.put(property, value);

????}

?

????/**

???? * 通過屬性名得到屬性值

???? *?@param?property屬性名

???? */

????public?Object getValue(String property) {

????????return?beanMap.get(property);

????}

?

????/**

???? * 得到該實體bean對象。

???? */

????public?Object getObject() {

????????return?this.object;

????}

?

????/**

???? * 生成Bean

???? *?@param?propertyMap

???? *?@return

???? */

????@SuppressWarnings("unchecked")

????private?Object generateBean(Map<String, Class> propertyMap) {

????????BeanGenerator generator =?new?BeanGenerator();

????????Set keySet = propertyMap.keySet();

????????for?(Iterator i = keySet.iterator(); i.hasNext();) {

????????????String key = (String) i.next();

????????????generator.addProperty(key, (Class) propertyMap.get(key));

????????}

????????return?generator.create();

????}

}

?

?

測試并使用動態Bean

?

import?java.lang.reflect.Method;

import?java.util.HashMap;

?

/**

* Cglib測試類

*/

public?class?CglibTest {

????@SuppressWarnings("unchecked")

????public?static?void?main(String[] args)?throws?ClassNotFoundException {

?

????????// 設置類成員屬性

????????HashMap<String, Class> propertyMap =?new?HashMap<String, Class>();

????????propertyMap.put("id", Class.forName("java.lang.Integer"));

????????propertyMap.put("name", Class.forName("java.lang.String"));

????????propertyMap.put("address", Class.forName("java.lang.String"));

?

????????// 生成動態Bean

????????CglibBean bean =?new?CglibBean(propertyMap);

?

????????// 給Bean設置值

????????bean.setValue("id",?new?Integer(123));

????????bean.setValue("name",?"454");

????????bean.setValue("address",?"789");

?

????????// 從Bean中獲取值,當然了獲得值的類型是Object

????????System.out.println(">>id="?+ bean.getValue("id"));

????????System.out.println(">>name="?+ bean.getValue("name"));

????????System.out.println(">>address="?+ bean.getValue("address"));// 獲得bean的實體

????????Object object = bean.getObject();

?

????????// 通過反射查看所有方法名

????????Class clazz = object.getClass();

????????Method[] methods = clazz.getDeclaredMethods();

????????for?(int?i = 0; i < methods.length; i++) {

????????????System.out.println(methods[i].getName());

????????}

????}

}

?

?

?

輸出:

>>id=123

>>name=454

>>address=789

setId

getAddress

getName

getId

setName

setAddress

class net.sf.cglib.empty.Object

BeanGeneratorByCGLIBBeanGeneratorByCGLIB

1d39cfaa

?

?

?

?

?

?

本篇學習文檔參考于:

http://jnb.ociweb.com/jnb/jnbNov2005.html

http://wenku.baidu.com/view/3f92297c27284b73f24250b9.html

http://www.cnblogs.com/icejoywoo/

http://www.blogjava.net/calvin/archive/2005/11/28/21741.html

http://m635674608.iteye.com/blog/1435221
等其他高手博客提供的資料。

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的CGLIB代理到底是个什么东西?这是一篇最全的CGLIB大全的全部內容,希望文章能夠幫你解決所遇到的問題。

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