簡體   English   中英

java動態代理與常規代理的有用性

[英]Usefulness of java dynamic proxies vs regular proxies

我需要一些建議,動態代理比常規代理更有用。

我已經投入了大量精力來學習如何有效地使用動態代理。 在這個問題中,拋開像AspectJ這樣的框架基本上可以執行我們嘗試使用動態代理實現的所有內容,或者例如CGLIB可以用來解決動態代理的一些缺點。

用例

  • 裝飾器 - 例如,執行方法調用的日志記錄,或緩存復雜操作的返回值
  • 堅持合同 - 即確保參數在可接受的范圍內,並且返回類型符合可接受的值。
  • 適配器 - 在某個地方看到一些巧妙的文章,描述它是如何有用的。 我很少遇到這種設計模式。

是其他人嗎?

動態代理優勢

  • 裝飾器:記錄所有方法調用,例如,

public Object invoke(Object target, Method method, Object[] arguments) {
         System.out.println("before method " + method.getName());
         return method.invoke(obj, args);
     }
}

裝飾器模式肯定是有用的,因為它允許所有代理方法的副作用(盡管這種行為是書籍 - 使用方面的例子..)。

  • 合同:與常規代理相比,我們不需要實現完整的接口。 例如,

public Object invoke(Object target, Method method, Object[] arguments) {
     if ("getValues".equals(method.getName()) {
         // check or transform parameters and/or return types, e.g., 
         return RangeUtils.validateResponse( method.invoke(obj, args) );
     }

     if ("getVersion".equals(method.getName()) {
         // another example with no delegation
         return 3;
     }
} 

另一方面,合同只能避免實現完整接口的需要。 然后,重構代理方法將無聲地使動態代理無效。

結論

所以我在這里看到的是一個真實的用例,一個有問題的用例。 你怎么看?

除了您所描述的內容之外,動態代理還有許多潛在用途 -

  1. 事件發布 - 在方法x()上,透明地調用y()或發送消息z。
  2. 事務管理(用於數據庫連接或其他事務操作)
  3. 線程管理 - 透明地解決昂貴的操作。
  4. 性能跟蹤 - 例如,由CountdownLatch檢查的定時操作。
  5. 連接管理 - 考慮像Salesforce的Enterprise API這樣的API,要求其服務的客戶端在執行任何操作之前啟動會話。
  6. 更改方法參數 - 如果您想要傳遞空值的默認值,如果這是您的事情。

除了上面描述的驗證和日志記錄之外,這些只是一些選項。 FWIW,JSR 303,一個bean驗證規范,在Hibernate Validator中有一個AOP風格的實現,所以你不需要專門為你的數據對象實現它。 Spring框架還內置了驗證功能,並且與AspectJ實現了很好的集成,可用於此處描述的一些內容。

事實上,AOP使大多數動態代理受益。 那是因為您可以在事先不知道的對象周圍創建動態代理。

動態代理的另一個有用的方面是當您想要對所有方法應用相同的操作時。 使用靜態代理,您需要大量重復的代碼(在每個代理方法上,您需要對方法進行相同的調用,然后委托給代理對象),動態代理將最小化這一點。

另請注意,Adapter和Decorator是單獨的模式。 它們在實現方式上看起來像代理模式(通過對象組合),但它們有不同的用途:

  • 裝飾器模式允許您擁有多個具體裝飾器,從而在運行時添加功能
  • 適配器模式旨在使對象適應不匹配的接口。 我能想到的最好的例子是EnumetationIterator - 它將Enumeration調整為Iterator接口。

我能想到的另一個用例是在運行時動態實現接口,這是一些框架的工作方式。

Retrofit為例,這是一個用於使用REST服務的Java庫。 您可以定義一個Java接口,該接口反映REST API中可用的操作,並使用注釋來裝飾方法以配置請求的細節。 很容易看出,在這種情況下,接口中定義的所有方法都必須對某個服務器執行HTTP請求,將方法參數轉換為請求參數; 然后將響應解析為定義為方法返回類型的java對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM