淺析Java中的動態(tài)代理
代理常見功能
日志代理
數(shù)據(jù)庫訪問的事務代理
代理模式的組成
- 抽象主題:通過接口或抽象類定義核心業(yè)務方法。
- 真實主題:實現(xiàn)了接口的實現(xiàn)類,是實施代理的具體對象。即代理最終代理的是具體的實現(xiàn)類類而不是接口。
- 代理:具有與代理對象相同的方法,可以控制和擴展被代理對象的功能,也是使用代理對象的根據(jù)目的。
代理對象 = 增強代碼 + 目標對象(原對象)
代理模式分類
靜態(tài)代理:代理類與被代理類一一對應,缺點是代理類太多。
動態(tài)代理:代理類是運行時通過反射技術動態(tài)生成的。有點是一類相似功能的被代理類(即需要相同擴展功能的類)只需要一個動態(tài)代理類。
動態(tài)代理實現(xiàn)的技術
JDK 代理:面向接口的代理,無法直接代理類,被代理的類必須實現(xiàn)某業(yè)務接口。
CGLIB 代理:功能更強,性能更好,可以直接代理類而不用實現(xiàn)接口,是通過動態(tài)創(chuàng)建被代理的子類重寫父類的被代理方法來實現(xiàn)統(tǒng)計附件功能的。不能代理final類或final方法。
JDK 代理的實現(xiàn)步驟
核心業(yè)務接口
public interface Buyer { /** * 賣房:核心業(yè)務方法 * @return */ String buy(); }
業(yè)務實現(xiàn)類
public class BuyerImpl implements Buyer{ public String buy() { System.out.println("本人賣房,從不坑人..."); return "一次搞定"; } }
動態(tài)代理類
public class BuyerInvocationHandler implements InvocationHandler { //被代理對象 private Object target; /** * 設置被代理對象 * @param target */ public void setTarget(Object target) { this.target = target; } /** * 執(zhí)行被代理對象的業(yè)務方法的代理方法 * @param proxy * @param method * @param args * @return * @throws Throwable */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("熬夜?jié)M大街收集電話號碼....."); //調(diào)用核心業(yè)務方法 Object result = method.invoke(target,args); System.out.println("不滿意,再找我..."); return result; } }
代理工廠類
public class BuyerProxyFactory { /** * 工廠方法 * @param target 需要被代理的對象 * @param <T> * @return 返回動態(tài)生成的代理對象 */ public static <T> T create(Object target){ // 創(chuàng)建動態(tài)代理對象 BuyerInvocationHandler handler = new BuyerInvocationHandler(); // 設置被代理對象 handler.setTarget(target); // 動態(tài)創(chuàng)建執(zhí)行業(yè)務方法的代理對象 return (T) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); } }
測試類
public class example { public static void main(String[] args) { //定義被代理對象 //定義被代理對象 Buyer buyer = new BuyerImpl(); buyer.buy(); // 直接調(diào)用業(yè)務方法,沒有代理的功能 // 使用代理工廠創(chuàng)建動態(tài)代理類對象 Buyer proxyBuyer = BuyerProxyFactory.create(buyer); proxyBuyer.buy(); } }
CGLIB 代理實現(xiàn)步驟
導入 POM
<dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>3.3.0</version> </dependency>
定義業(yè)務方法
public class OrderService { public int insert(){ System.out.println("添加訂單...."); return 0; } }
定義代理工廠類,與提供事務控制功能的MethodInterceptor合二為一
public class TransactionProxyFactory { /** * 動態(tài)創(chuàng)建被代理類的代理對象 * @param clazz 類型 * @param <T> * @return 代理對象 */ public static <T> T create(Class<T> clazz){ Enhancer enhancer = new Enhancer(); // 采用接口內(nèi)部類的方式實現(xiàn)代理功能 enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("開始事務。。。。"); // 核心業(yè)務,調(diào)用父類的方法 Object result = methodProxy.invokeSuper(target,objects); System.out.println("提交或回滾事務...."); return result; } }); // 設置代理類的父類 enhancer.setSuperclass(clazz); // 返回創(chuàng)建的動態(tài)代理類對象 return (T) enhancer.create(); } }
測試類
public class TransactionProxyFactoryTest { public static void main(String[] args) { // 使用代理創(chuàng)建業(yè)務邏輯類 OrderService orderService = TransactionProxyFactory.create(OrderService.class); orderService.insert(); CartService cartService = TransactionProxyFactory.create(CartService.class); cartService.insert(); } }
到此這篇關于淺析Java中的動態(tài)代理的文章就介紹到這了,更多相關Java動態(tài)代理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringCloud之消息總線Spring Cloud Bus實例代碼
這篇文章主要介紹了SpringCloud之消息總線Spring Cloud Bus實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04springboot整合JSR303校驗功能實現(xiàn)代碼
這篇文章主要介紹了springboot整合JSR303校驗功能實現(xiàn),JSR303校驗方法有統(tǒng)一校驗的需求,統(tǒng)一校驗實現(xiàn)以及分組校驗,本文結合實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2023-01-01Mybatis-Plus同時使用邏輯刪除和唯一索引的問題及解決辦法(報數(shù)據(jù)重復Duplicate entry的
在開發(fā)中,我們經(jīng)常會有邏輯刪除和唯一索引同時使用的情況,但當使用mybatis plus時,如果同時使用邏輯刪除和唯一索引,會報數(shù)據(jù)重復Duplicate entry的問題,如何解決這個問題呢,小編給大家分享Mybatis-Plus同時使用邏輯刪除和唯一索引的問題及解決辦法,一起看看吧2023-11-11