使用djcproxy创建代理对象
在過去的幾周中,我展示了如何使用Java Reflection API和cglib創建代理對象。 在本文中,我將向您展示如何使用djcproxy做到這一點。
哦,不是,另一個代理實現!
除了我創建此代理的自私事實之外,還要寫些什么呢? 關鍵是這是一個用Java編寫的代理,它創建了可以檢查的Java代碼。 它還可以即時編譯和加載創建的Java類,因此它也可以使用,但主要優點是您可以輕松了解動態代理的工作原理。 至少比深入研究cglib的代碼要容易得多,后者直接創建字節碼。
如何使用它
您可以從github獲取源代碼,也可以將依賴項添加到項目maven pom中。
<dependency><groupId>com.javax0</groupId><artifactId>djcproxy</artifactId><version>2.0.3</version> </dependency>之后,您可以使用以下代碼:
class A {public int method() {return 1;} } class Interceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args,MethodProxy mproxy) throws Exception {if (method.getName().equals("toString")) {return "interceptedToString";}return 0;} }...A a = new A();ProxyFactory<A> factory = new ProxyFactory<>();A s = factory.create(a, new Interceptor());可以在GitHub中的項目測試中找到此代碼。 這是一個易于編輯的易于編輯的縮寫版本。
類“ A”是原始類,當我們要創建新的代理對象時,我們將創建一個已存在對象的代理。 這不同于反射或屈服。 如果使用cgilib,您將創建一個代理對象,它“包含”原始對象。 從OO術語來看,它并不是真正的包含,因為代理類擴展了原始類。 但是,由于此擴展,代理對象也是原始類的實例。 Cgilib并不真正在乎您要攔截哪個類實例(對象)。 如果需要,可以將對任何對象實例的引用注入到攔截器中。 Djcproxy使用了一種不同的方法,它可以為您做到這一點,在攔截器中,您將獲得此對象作為參數傳遞。 這就是為什么您必須在第20行實例化該對象的原因。
Interceptor實現了庫中也提供的接口MethodInterceptor 。 它只有一種方法: intercept ,在調用代理對象方法時調用。 參數是
- obj –原始對象
- method –在代理對象中調用的方法
- args –傳遞給代理對象上的方法調用的參數。 注意原始參數將被裝箱。
- mproxy –方法代理,可用于在原始對象上或僅在相同類型的任何其他對象上調用方法
這就是關于如何使用該庫的全部內容。 接下來的事情是查看生成的內容,以便您可以更好地了解代理的工作方式。 即使您使用其他代理,洞察力也不會傷害您。 當您了解所使用的庫的原理時,很多時候調試或僅生成更好的代碼會更容易。
盡管cglib為您提供了一個靜態工廠方法來創建新對象,但djcproxy要求您創建一個代理工廠。 這是在21上方的行上顯示的。如果要像使用cglib一樣使用它,則可以在要使用其工廠的類中聲明一個靜態ProxyFactory字段。 另一方面,可能在代碼的不同部分具有不同的工廠。 盡管它的優點很少,但是我仍然相信它比提供靜態工廠方法更干凈。
代理如何工作?
此程序包中的另一件事是,它使您可以訪問生成的源。 您可以插入行
String generatedSource = factory.getGeneratedSource();System.out.println(generatedSource);打印出生成的代理類,這是經過某種格式設置的:
package com.javax0.djcproxy;class PROXY$CLASS$A extends com.javax0.djcproxy.ProxyFactoryTest.A implements com.javax0.djcproxy.ProxySetter {com.javax0.djcproxy.ProxyFactoryTest.A PROXY$OBJECT = null;com.javax0.djcproxy.MethodInterceptor PROXY$INTERCEPTOR = null;public void setPROXY$OBJECT(java.lang.Object PROXY$OBJECT) {this.PROXY$OBJECT = (com.javax0.djcproxy.ProxyFactoryTest.A) PROXY$OBJECT;}public void setPROXY$INTERCEPTOR(com.javax0.djcproxy.MethodInterceptor PROXY$INTERCEPTOR) {this.PROXY$INTERCEPTOR = PROXY$INTERCEPTOR;}PROXY$CLASS$A() {super();}private com.javax0.djcproxy.MethodProxy method_MethodProxyInstance = null;@Overridepublic int method() {try {if (null == method_MethodProxyInstance) {method_MethodProxyInstance = new com.javax0.djcproxy.MethodProxy() {public java.lang.Object invoke(java.lang.Object obj, java.lang.Object[] args) throws Throwable {return ((com.javax0.djcproxy.ProxyFactoryTest.A) obj).method();}};}return (int) PROXY$INTERCEPTOR.intercept(PROXY$OBJECT, PROXY$OBJECT.getClass().getMethod("method", new Class[]{}),new Object[]{}, method_MethodProxyInstance);} catch (Throwable e) {throw new RuntimeException(e);}}... other overridden methods deleted ...}請注意,對于此生成的代碼,類A是ProxyFactoryTest的靜態嵌套類。
有趣的代碼是方法method()的重載。 (對不起這個名字。對于一個什么都不做的方法,我有一個更好的名字。我不MethodProxy 。)讓我們跳過該部分,檢查該方法是否已經存在MethodProxy實例,如果缺少則創建一個。 方法method()實際上會調用我們定義的攔截器對象,并傳遞代理對象,反射方法對象,參數以及方法代理。
什么是方法代理
該名稱可能首先引起混淆,因為我們已經有一個“對象”代理。 原始類的每個方法都有一個單獨的方法代理。 這些可用于調用原始方法,而無需進行反射調用。 這加快了代理的使用。 您還可以在cglib中找到此調用和類似的機制。
筆記
該實現有一些流程,例如,后方法代理實例化實際上沒有優勢,但同時在代理的多線程執行情況下可能會受到損害。 還可以創建一個不僅擴展類而且實現任意接口的代理對象(也許某些擴展類甚至沒有實現)。 該實現在github上也有一些其他業余愛好開源項目中使用,我將來可能會寫有關該項目的信息。 它們比生產代碼更具說明性,教育性和概念證明性項目。 如果您對實施,想法或任何意見有任何意見,請給我您的意見。
翻譯自: https://www.javacodegeeks.com/2016/02/creating-proxy-object-using-djcproxy.html
總結
以上是生活随笔為你收集整理的使用djcproxy创建代理对象的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 笔记本电脑怎么安装软件(笔记本电脑怎么安
- 下一篇: 投资银行对Java进行的二十大核心面试问
