Java進階之 JDK動態代理與Cglib動態代理
與靜態代理對照(關於靜態代理的介紹 可以閱讀上一篇:JAVA設計模式之 代理模式【Proxy Pattern】),
動態代理類的位元組碼是在程式執行時由Java反射機制動態生成。
注意:1、AspectJ是採用編譯時生成AOP代理類,具有更好的效能,但是需要使用特定的編譯器進行處理
2、Spring AOP採用執行時生成AOP代理類,無需使用特定編譯器進行處理,但是效能相對於AspectJ較差
二、JDK動態代理 [對有實現介面的物件做代理]
1、JDK動態代理中 需要了解的兩個重要的類或介面 [InvocationHandler 和 Proxy]
① InvocationHandler介面
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
引數說明: Object proxy:指被代理的物件
Method method:我們所要呼叫被代理物件的某個方法的Method物件
Object[] args:被代理物件某個方法呼叫時所需要的引數
可以將InvocationHandler介面的子類想象成一個代理的最終操作類。
說明:每一個動態代理類都必須要實現InvocationHandler這個介面,並且每個代理類(Proxy)的例項都關聯到了一個handler,當我們通過代理物件呼叫一個方法的時候,這個方法的呼叫就會被轉發為由InvocationHandler這個介面的 invoke 方法來進行呼叫。同時在invoke的方法裡 我們可以對被代理物件的方法呼叫做增強處理(如新增事務、日誌、許可權驗證等操作)。
② Proxy類
Proxy類是專門完成代理的操作類,可以通過此類為一個或多個介面動態地生成實現類,該類常用的呼叫方法如下:
newProxyInstance方法引數說明如下:
ClassLoader loader:類載入器,定義了由哪個ClassLoader物件來對生成的代理物件進行載入
Class<?>[] interfaces:得到被代理類全部的介面,如果我提供了一組介面給它,那麼這個代理物件就宣稱實現了該介面,這樣我就能呼叫這組介面中的方法了
InvocationHandler h:得到InvocationHandler介面的子類例項
2、JDK動態代理程式碼示例:
首先我們定義了一個Subject型別的介面:Subject.java
public interface Subject {
public void visit();
}
接著定義一個介面的實現類,這個類就是我們示例中的被代理物件:RealSubject.java/**
* 被代理類
* @author lvzb.software@qq.com
*
*/
public class RealSubject implements Subject {
@Override
public void visit() {
System.out.println("I am 'RealSubject',I am the execution method");
}
}
第三步 定義一個動態代理類(必須要實現 InvocationHandler 這個介面):DynamicProxy.javaimport java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* JDK動態代理類
* @author lvzb.software@qq.com
*
*/
public class DynamicProxy implements InvocationHandler {
// 我們要代理的真實物件(委託物件)
private Object subject;
// 構造方法,給我們要代理的真實物件賦初值
public DynamicProxy(Object obj){
this.subject = obj;
}
@Override
public Object invoke(Object object, Method method, Object[] args)
throws Throwable {
// 在代理真實物件操作前 我們可以新增一些自己的操作
System.out.println("before proxy invoke");
// 當代理物件呼叫真實物件的方法時,其會自動的跳轉到代理物件關聯的handler物件的invoke方法來進行呼叫
method.invoke(subject, args);
// 在代理真實物件操作後 我們也可以新增一些自己的操作
System.out.println("after proxy invoke");
return null;
}
}
最後代理測試類:Client.javaimport java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
// 我們要代理的真實物件
Subject realSubject = new RealSubject();
// 我們要代理哪個真實物件,就將該物件傳進去,最後是通過該真實物件呼叫方法的
InvocationHandler handler = new DynamicProxy(realSubject);
/*
* 通過Proxy的newProxyInstance方法來動態建立我們的代理物件,我們來看看其三個引數<br/>
* 引數一:我們這裡使用handler這個類的ClassLoader物件來載入我們的代理物件<br/>
* 引數二:我們這裡為代理物件提供的介面是真實物件所實行的介面,表示我要代理的是該真實物件,這樣我就能呼叫這組介面中的方法了<br/>
* 引數三:我們這裡將這個代理物件關聯到了上方的 InvocationHandler 這個物件上
*/
Subject proxyInstance = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(),
RealSubject.class.getInterfaces(),
handler);
System.out.println(proxyInstance.getClass().getName());
proxyInstance.visit();
}
}
執行->控制檯輸出結果如下:
com.sun.proxy.$Proxy0
before proxy invoke
I am 'RealSubject',I am the execution method
after proxy invoke
三、Cglib(Code Generation Library)動態代理 [對沒有實現介面的普通類做代理]
1、概述:
Cglib是一個優秀的動態代理框架,它的底層使用ASM(JAVA位元組碼處理框架)在記憶體中動態的生成被代理類的子類。使用CGLIB即使被代理類沒有實現任何介面也可以實現動態代理功能。但是不能對final修飾的類進行代理。
2、原理:
通過位元組碼技術為一個類建立子類,並在子類中採用方法攔截的技術攔截所有父類方法的呼叫。
<JDK動態代理與CGLib動態代理均是實現Spring AOP的基礎>
3、使用:
使用Cglib前需要匯入以下兩個jar檔案:
asm.jar – Cglib的底層實現。
【cglib包的底層是使用位元組碼處理框架ASM來轉換位元組碼並生成新的類,所以cglib包要依賴於asm包】
cglib.jar - Cglib的核心jar包。
4、Cglib動態代理程式碼示例:
首先定義一個沒有實現介面的代理委託類:CglibRealSubject.java
/**
* 沒有實現介面的代理委託類
* @author lvzb.software@qq.com
*
*/
public class CglibRealSubject{
public void visit() {
System.out.println("I am 'RealSubject',I am the execution method");
}
}
接著定義一個Cglib動態代理類: CglibDynamicProxy.java
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 使用cglib動態代理
* @author lvzb.software@qq.com
*
*/
public class CglibDynamicProxy implements MethodInterceptor {
private Object target;
/**
* 建立代理物件
* @param target 被代理的物件
* @return
*/
public Object getProxyInstance(Object target){
this.target = target;
// 宣告增強類例項
Enhancer enhancer = new Enhancer();
// 設定被代理類位元組碼,CGLIB根據位元組碼生成被代理類的子類
enhancer.setSuperclass(this.target.getClass());
// 設定要代理的攔截器,回撥函式,即一個方法攔截 new MethodInterceptor()
enhancer.setCallback(this);
// 建立代理物件 例項
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
// 在代理真實物件操作前 我們可以新增一些自己的操作
System.out.println("前置代理,增強處理");
proxy.invokeSuper(obj, args);
// 在代理真實物件操作後 我們也可以新增一些自己的操作
System.out.println("後置代理,增強處理");
return null;
}
}
最後測試客戶端類:CglibClient.java
public class CglibClient {
public static void main(String[] args) {
CglibDynamicProxy cglib = new CglibDynamicProxy();
CglibRealSubject realSubject = (CglibRealSubject) cglib.getProxyInstance(new CglibRealSubject());
realSubject.visit();
}
}
執行->控制檯輸出結果如下:
前置代理,增強處理
I am 'RealSubject',I am the execution method
後置代理,增強處理
四、擴充套件學習
關於什麼是AOP思想?Spring AOP實現原理?及什麼樣的系統業務場景我們可以使用到AOP這種動態代理技術?
小呂推薦一篇非常值得閱讀和學習的文章: Spring AOP實現原理與CGLIB應用
—————————————————————————————————————
如果文章內容對您有幫助, 不要忘記 頂 一下,來支援一下哦!
如果您對文章內容有任何疑問或有更好的見解, 可以通過評論留言或發郵件的方式聯絡我:
ice_zhengbin@163.com
如果需要轉載,請註明出處,謝謝!!
—————————————————————————————————————
相關文章
- Java代理(jdk靜態代理、動態代理和cglib動態代理)JavaJDKCGLib
- 代理模式詳解:靜態代理、JDK動態代理與Cglib動態代理模式JDKCGLib
- Java動態代理(JDK和cglib)JavaJDKCGLib
- JDK動態代理和 CGLIB 代理JDKCGLib
- JDK動態代理和CGLib代理JDKCGLib
- (轉)Java動態代理與CGLib代理JavaCGLib
- cglib動態代理和jdk動態代理的區別與應用CGLibJDK
- 靜態代理和動態代理(jdk/cglib)詳解JDKCGLib
- spring aop原理 JDK動態代理和CGLIB動態代理SpringJDKCGLib
- 你必須會的 JDK 動態代理和 CGLIB 動態代理JDKCGLib
- Java進階--Java動態代理Java
- CGLib 動態代理CGLib
- Java JDK Proxy和CGLib動態代理示例講解JavaJDKCGLib
- 動態代理jdk的Proxy與spring的CGlibJDKSpringCGLib
- 3.靜態代理&動態代理&CGlibCGLib
- 動態代理jdk和cglib的區別JDKCGLib
- 最詳細的代理講解--JDK動態代理和cglib代理JDKCGLib
- Spring動態代理的生成-如何判斷是使用JDK動態代理還是CGlib代理SpringJDKCGLib
- 深入理解靜態代理與JDK動態代理JDK
- 動態代理-cglib分析CGLib
- Java動態代理 jdk和cglib的實現比較JavaJDKCGLib
- JDK動態代理JDK
- 設計模式之cglib動態代理設計模式CGLib
- 【JAVA】代理模式之Java動態代理Java模式
- Java架構-Java JDK 動態代理Java架構JDK
- CGlib動態代理複習CGLib
- JDK動態代理初探JDK
- JAVA 靜態代理 & 動態代理Java
- JDK 和 CGLib 實現動態代理和區別JDKCGLib
- Java提高班(六)反射和動態代理(JDK Proxy和Cglib)Java反射JDKCGLib
- jdk proxy invocationhandler (jdk動態代理)JDK
- Java Web之動態代理JavaWeb
- java靜態代理和動態代理Java
- Jmh測試JDK,CGLIB,JAVASSIST動態代理方式的效能JDKCGLibJava
- 面試造火箭系列,栽在了cglib和jdk動態代理面試CGLibJDK
- 【4】JDK和CGLIB生成動態代理類的區別JDKCGLib
- JDK動態代理詳解JDK
- 深挖JDK動態代理(一)JDK