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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

【设计模式】代理模式 ( 动态代理 )

發(fā)布時間:2025/6/17 asp.net 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【设计模式】代理模式 ( 动态代理 ) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 一、動態(tài)代理使用流程
  • 二、動態(tài)代理代碼示例
    • 1、訂單類
    • 2、Service 接口
    • 3、Service 實(shí)現(xiàn)類
    • 4、Service 靜態(tài)代理類
    • 5、Dao 接口
    • 6、Dao 實(shí)現(xiàn)類
    • 7、Service 動態(tài)代理類
    • 8、測試類
  • 三、動態(tài)代理源碼分析





一、動態(tài)代理使用流程



動態(tài)的代理類使用流程 :

1. 內(nèi)部持有 目標(biāo)對象2. 創(chuàng)建動態(tài)代理類 , 調(diào)用 Proxy.newProxyInstance 創(chuàng)建動態(tài)代理類系統(tǒng)會自動創(chuàng)建一個類 , 該類實(shí)現(xiàn)了目標(biāo)對象的所有接口的所有方法最后返回一個該動態(tài)代理類的實(shí)例對象3. 調(diào)用動態(tài)代理類實(shí)例對象的某個接口方法 , 會自動回調(diào) 動態(tài)代理類的 invoke 函數(shù)注意 : 被代理的方法必須是 目標(biāo)對象 的接口中的方法



二、動態(tài)代理代碼示例



業(yè)務(wù)場景 : 保存訂單信息 , 在 Service 層處理訂單保存 , 在 Dao 層將訂單存儲到數(shù)據(jù)庫 ; 使用動態(tài)代理類加強(qiáng) Service 層的功能 ;


1、訂單類


package proxy;/*** 訂單類* 存儲訂單時 , 通過 Service 層通接收 Order 對象進(jìn)行處理*/ public class Order {/*** 訂單信息*/private Object orderInfo;/*** 用戶 ID*/private Integer userId;public Order(Object orderInfo, Integer userId) {this.orderInfo = orderInfo;this.userId = userId;}public Object getOrderInfo() {return orderInfo;}public void setOrderInfo(Object orderInfo) {this.orderInfo = orderInfo;}public Integer getUserId() {return userId;}public void setUserId(Integer userId) {this.userId = userId;} }

2、Service 接口


package proxy;/*** 服務(wù)接口*/ public interface IOrderService {/*** 保存訂單* @param order 數(shù)據(jù)庫生效行數(shù)* @return*/int saveOrder(Order order); }

3、Service 實(shí)現(xiàn)類


package proxy;public class OrderServiceImpl implements IOrderService {private IOrderDao iOrderDao;public OrderServiceImpl(IOrderDao iOrderDao) {this.iOrderDao = iOrderDao;}@Overridepublic int saveOrder(Order order) {System.out.println("Service 層插入 Order 訂單信息成功");return this.iOrderDao.insert(order);} }

4、Service 靜態(tài)代理類


package proxy;/*** 訂單服務(wù)靜態(tài)代理類*/ public class OrderServiceStaticProxy {private IOrderService iOrderService;public OrderServiceStaticProxy(IOrderService iOrderService) {this.iOrderService = iOrderService;}public int saveOrder(Order order){beforeMethod();int result = iOrderService.saveOrder(order);afterMethod();return result;}/*** 在被代理對象方法之前執(zhí)行的內(nèi)容*/private void beforeMethod() {System.out.println("靜態(tài)代理 OrderServiceStaticProxy 執(zhí)行 saveOrder 之前");}/*** 在被代理對象方法之后執(zhí)行的內(nèi)容*/private void afterMethod() {System.out.println("靜態(tài)代理 OrderServiceStaticProxy 執(zhí)行 saveOrder 之后");} }

5、Dao 接口


package proxy;/*** 數(shù)據(jù)庫接口*/ public interface IOrderDao {/*** 向數(shù)據(jù)庫中插入訂單信息* @param order* @return*/int insert(Order order); }

6、Dao 實(shí)現(xiàn)類


package proxy;public class OrderDaoImpl implements IOrderDao {@Overridepublic int insert(Order order) {System.out.println("Dao 層插入 Order 訂單信息成功");return 1;} }

7、Service 動態(tài)代理類


package proxy;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;/*** 訂單服務(wù)動態(tài)代理類** 動態(tài)的代理類使用流程 :* 1. 內(nèi)部持有 目標(biāo)對象* 2. 創(chuàng)建動態(tài)代理類 , 調(diào)用 Proxy.newProxyInstance 創(chuàng)建動態(tài)代理類* 系統(tǒng)會自動創(chuàng)建一個類 , 該類實(shí)現(xiàn)了目標(biāo)對象的所有接口的所有方法* 最后返回一個該動態(tài)代理類的實(shí)例對象* 3. 調(diào)用動態(tài)代理類實(shí)例對象的某個接口方法 , 會自動回調(diào) 動態(tài)代理類的 invoke 函數(shù)* 注意 : 被代理的方法必須是 目標(biāo)對象 的接口中的方法*/ public class OrderServiceDynamicProxy implements InvocationHandler {private Object target;public OrderServiceDynamicProxy(IOrderService iOrderService) {this.target = iOrderService;}/*** 綁定方法* 將目標(biāo)對象與動態(tài)代理類進(jìn)行綁定*/public Object bind() {// 拿到目標(biāo)對象的類Class clazz = target.getClass();// 動態(tài)代理類時系統(tǒng)執(zhí)行的時候自動生成的類 , 該類自動實(shí)現(xiàn)了指定的接口// 動態(tài)代理類會獲取目標(biāo)對象的所有接口 , 并實(shí)現(xiàn)所有的接口中的所有的方法// 該動態(tài)代理類 代理的是 target 的接口的方法 , 即 IOrderService 接口的方法// 凡是調(diào)用創(chuàng)建的動態(tài)代理實(shí)例對象中的 IOrderService 接口方法 , 都會觸發(fā)該類的 invoke 方法return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);}/*** 調(diào)用代理類的 IOrderService 接口方法 , 就會自動回調(diào)該方法* 注意 : 所有的 IOrderService 接口方法 , 都會回調(diào)該方法* 在回調(diào)時 , 需要判定一下 , 是哪個方法回調(diào)的 , 過濾掉不需要加強(qiáng)的方法** @param proxy 該參數(shù)幾乎用不到* @param method 要被增強(qiáng)的方法對象* @param args 要被增強(qiáng)的方法對象的參數(shù)* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {beforeMethod();// 調(diào)用目標(biāo)對象的 method 方法Object object = method.invoke(target, args);afterMethod();return object;}/*** 在被代理對象方法之前執(zhí)行的內(nèi)容*/private void beforeMethod() {System.out.println("動態(tài)代理 OrderServiceStaticProxy 執(zhí)行 saveOrder 之前");}/*** 在被代理對象方法之后執(zhí)行的內(nèi)容*/private void afterMethod() {System.out.println("動態(tài)代理 OrderServiceStaticProxy 執(zhí)行 saveOrder 之后");}}

8、測試類


package proxy;public class Main {public static void main(String[] args) {Order order = new Order("書籍訂單", 1);IOrderDao dao = new OrderDaoImpl();IOrderService service = new OrderServiceImpl(dao);// 不使用代理的情況service.saveOrder(order);System.out.println();// 使用靜態(tài)代理的情況OrderServiceStaticProxy proxy = new OrderServiceStaticProxy(service);proxy.saveOrder(order);System.out.println();// 使用動態(tài)代理的情況IOrderService orderServiceDynamicProxy = (IOrderService) new OrderServiceDynamicProxy(service).bind();orderServiceDynamicProxy.saveOrder(order);} }

執(zhí)行結(jié)果 :

Service 層插入 Order 訂單信息成功 Dao 層插入 Order 訂單信息成功靜態(tài)代理 OrderServiceStaticProxy 執(zhí)行 saveOrder 之前 Service 層插入 Order 訂單信息成功 Dao 層插入 Order 訂單信息成功 靜態(tài)代理 OrderServiceStaticProxy 執(zhí)行 saveOrder 之后動態(tài)代理 OrderServiceStaticProxy 執(zhí)行 saveOrder 之前 Service 層插入 Order 訂單信息成功 Dao 層插入 Order 訂單信息成功 動態(tài)代理 OrderServiceStaticProxy 執(zhí)行 saveOrder 之后





三、動態(tài)代理源碼分析



動態(tài)代理的核心步驟是 Proxy.newProxyInstance 調(diào)用 ;

傳入 333 個參數(shù)分別是 : ① 目標(biāo)對象類加載器 , ② 目標(biāo)對象實(shí)現(xiàn)的接口 , ③ 動態(tài)代理類本身 ( InvocationHandler 實(shí)現(xiàn)類 ) ;


public class Proxy implements java.io.Serializable {/*** Returns an instance of a proxy class for the specified interfaces* that dispatches method invocations to the specified invocation* handler.** <p>{@code Proxy.newProxyInstance} throws* {@code IllegalArgumentException} for the same reasons that* {@code Proxy.getProxyClass} does.** @param loader the class loader to define the proxy class* @param interfaces the list of interfaces for the proxy class* to implement* @param h the invocation handler to dispatch method invocations to* @return a proxy instance with the specified invocation handler of a* proxy class that is defined by the specified class loader* and that implements the specified interfaces* @throws IllegalArgumentException if any of the restrictions on the* parameters that may be passed to {@code getProxyClass}* are violated* @throws SecurityException if a security manager, <em>s</em>, is present* and any of the following conditions is met:* <ul>* <li> the given {@code loader} is {@code null} and* the caller's class loader is not {@code null} and the* invocation of {@link SecurityManager#checkPermission* s.checkPermission} with* {@code RuntimePermission("getClassLoader")} permission* denies access;</li>* <li> for each proxy interface, {@code intf},* the caller's class loader is not the same as or an* ancestor of the class loader for {@code intf} and* invocation of {@link SecurityManager#checkPackageAccess* s.checkPackageAccess()} denies access to {@code intf};</li>* <li> any of the given proxy interfaces is non-public and the* caller class is not in the same {@linkplain Package runtime package}* as the non-public interface and the invocation of* {@link SecurityManager#checkPermission s.checkPermission} with* {@code ReflectPermission("newProxyInPackage.{package name}")}* permission denies access.</li>* </ul>* @throws NullPointerException if the {@code interfaces} array* argument or any of its elements are {@code null}, or* if the invocation handler, {@code h}, is* {@code null}*/@CallerSensitivepublic static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{// 進(jìn)行空校驗(yàn) Objects.requireNonNull(h);// 對傳入的接口進(jìn)行安全檢查 final Class<?>[] intfs = interfaces.clone();final SecurityManager sm = System.getSecurityManager();if (sm != null) {checkProxyAccess(Reflection.getCallerClass(), loader, intfs);}// 動態(tài)代理的思路是生成一個新類/** 動態(tài)生成一個代理類*/Class<?> cl = getProxyClass0(loader, intfs);/** Invoke its constructor with the designated invocation handler.*/try {if (sm != null) {checkNewProxyPermission(Reflection.getCallerClass(), cl);}// 通過反射獲取代理類的構(gòu)造函數(shù) , 并根據(jù)構(gòu)造函數(shù)生成實(shí)例對象 final Constructor<?> cons = cl.getConstructor(constructorParams);final InvocationHandler ih = h;if (!Modifier.isPublic(cl.getModifiers())) {AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {cons.setAccessible(true);return null;}});}// 返回動態(tài)代理類生成的實(shí)例對象return cons.newInstance(new Object[]{h});} catch (IllegalAccessException|InstantiationException e) {throw new InternalError(e.toString(), e);} catch (InvocationTargetException e) {Throwable t = e.getCause();if (t instanceof RuntimeException) {throw (RuntimeException) t;} else {throw new InternalError(t.toString(), t);}} catch (NoSuchMethodException e) {throw new InternalError(e.toString(), e);}}/*** Generate a proxy class. Must call the checkProxyAccess method* to perform permission checks before calling this.*/private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {if (interfaces.length > 65535) {// 判定接口數(shù)量 , 接口不能超過 65535 個 throw new IllegalArgumentException("interface limit exceeded");}// If the proxy class defined by the given loader implementing// the given interfaces exists, this will simply return the cached copy;// otherwise, it will create the proxy class via the ProxyClassFactory// 代理類生成的 Class 都緩存在此 , 如果緩存中有這個代理類 , 直接獲取 // 如果緩存中 , 沒有這個代理類 , 創(chuàng)建這個代理類 return proxyClassCache.get(loader, interfaces);}/*** Look-up the value through the cache. This always evaluates the* {@code subKeyFactory} function and optionally evaluates* {@code valueFactory} function if there is no entry in the cache for given* pair of (key, subKey) or the entry has already been cleared.** @param key possibly null key* @param parameter parameter used together with key to create sub-key and* value (should not be null)* @return the cached value (never null)* @throws NullPointerException if {@code parameter} passed in or* {@code sub-key} calculated by* {@code subKeyFactory} or {@code value}* calculated by {@code valueFactory} is null.*/public V get(K key, P parameter) {Objects.requireNonNull(parameter);expungeStaleEntries();Object cacheKey = CacheKey.valueOf(key, refQueue);// lazily install the 2nd level valuesMap for the particular cacheKeyConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);if (valuesMap == null) {ConcurrentMap<Object, Supplier<V>> oldValuesMap= map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>());if (oldValuesMap != null) {valuesMap = oldValuesMap;}}// create subKey and retrieve the possible Supplier<V> stored by that// subKey from valuesMapObject subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));Supplier<V> supplier = valuesMap.get(subKey);Factory factory = null;while (true) {// 如果找到對應(yīng)的類 , 直接返回 if (supplier != null) {// supplier might be a Factory or a CacheValue<V> instanceV value = supplier.get();if (value != null) {return value;}}// 如果緩存中沒有這個類 , 開始創(chuàng)建這個類// else no supplier in cache// or a supplier that returned null (could be a cleared CacheValue// or a Factory that wasn't successful in installing the CacheValue)// lazily construct a Factoryif (factory == null) {factory = new Factory(key, parameter, subKey, valuesMap);}if (supplier == null) {supplier = valuesMap.putIfAbsent(subKey, factory);if (supplier == null) {// successfully installed Factorysupplier = factory;}// else retry with winning supplier} else {if (valuesMap.replace(subKey, supplier, factory)) {// successfully replaced// cleared CacheEntry / unsuccessful Factory// with our Factorysupplier = factory;} else {// retry with current suppliersupplier = valuesMap.get(subKey);}}}} }

總結(jié)

以上是生活随笔為你收集整理的【设计模式】代理模式 ( 动态代理 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。