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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态代理JDK于cglib

發布時間:2023/12/3 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态代理JDK于cglib 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

靜態代理的缺點:

1、由于靜態代理中的代理類是針對某一個類去做代理的,那么假設一個系統中有100個Service,則需要創建100個代理類
2、如果一個Service中有很多方法需要事務(增強動作),發現代理對象的方法中還是有很多重復的代碼
3、由第一點和第二點可以得出:靜態代理的重用性不強
那怎么解決呢?
用動態代理就可以很好的解決上述問題,本篇介紹一下:Java中的動態代理
動態代理實現的目的和靜態代理一樣,都是對目標方法進行增強,而且讓增強的動作和目標動作分開,達到解耦的目的
動態代理分為JDK的動態代理和cglib動態代理,他倆有略微的差別:cglib動態代理產生的代理對象是目標對象的子類。
下面分別介紹JDK的動態代理(是JDK的代碼實現的)和cglib動態代理(是cglib的jar包實現的)

JDK的動態代理

Interface

package com.itheima.proxy;/*** 對生產常見的要求*/ public interface IProducer {/*** 銷售* @param money*/public void saleProduct(float money);/*** 售后* @param money*/public void afterServer(float money); }

Producer

package com.itheima.proxy;/*** 一個生產者[需要符合代理商的要求,代理商的要求是 要有銷售和售后]*/ public class Producer implements IProducer {/*** 銷售** @param money*/public void saleProduct(float money) {System.out.println("拿到錢,賣出產品"+money);}/*** 售后** @param money*/public void afterServer(float money) {System.out.println("提供售后服務,并拿到錢"+money);} }

client

package com.itheima.proxy;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;/*** 模擬一個消費者*/ public class client {public static void main(String[] args) {//生產者final Producer producer = new Producer();/*** 動態代理* 特點:字節碼 隨用隨創建,隨用隨加載* 作用:不修改源碼的基礎上對方法增強* 分類:基于接口的動態代理* 設計的類 peoxy* 提供者:JDK官方** 基于子類的動態代理*如何創建代理對象* 使用Proxy類中的newProxyInstance方法*創建代理對象的要求* 被代理類必須實現一個接口,如果沒有則不能使用* newProxyInstance 參數* ClassLoader:類加載器* 它是用于加載代理對象的字節碼的,和被代理對象使用相同的類加載器 固定寫法* class[]:字節碼數組* 它是用于讓代理對象和被代理對象有相同的方法。 固定寫法* InvocationHandler :用于提供增強的代碼* 它是讓我們寫如何代理,我們一般都是寫一個該接口的實現類,通常情況下都是匿名內部類,但不是必須的* 此接口的實現類都是誰用誰寫**//*代理對象為 iProducer。被代理對象producer*/IProducer iProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() {/*** 作用:執行被代理對象的任何接口方法都會經過該方法* @param proxy 代理對象的引用* @param method 當前執行的方法* @param args 當前執行方法的參數* @return 和被代理對象方法有相同的返回值* @throws Throwable*/public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 提供增強的代碼Object returnValue = null; // 獲取方法執行的參數Float money = (Float) args[0]; // 判斷當前的方法是不是銷售if ("saleProduct".equals(method.getName())) {returnValue = method.invoke(producer, money * 0.8f);} else {returnValue = method.invoke(producer, money * 0.08f);}return returnValue;}});iProducer.saleProduct(10000f);iProducer.afterServer(1000f);} }
結果
拿到錢,賣出產品8000.0 提供售后服務,并拿到錢80.0

cglib動態代理

client

package com.itheima.cglib;import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class client {public static void main(String[] args) {final Producer producer = new Producer();/*動態代理:特點:字節碼隨用隨創建,隨用隨加載作用:在不修改源碼的基礎上對方法增強分類:基于接口的動態代理基于子類的動態代理涉及的類:Enhancer提供者: 第三方cglib庫如何創建代理對象:使用Enhance類中的create方法創建代理對象的要求:被代理對象的類不能是最終類create方法的參數class:字節碼它是用于指定被代理對象的字節碼CallBack:用于提供增強的代碼它是讓我們寫如何代理,我們一般都是寫一個該接口的實現類,通常情況下采用匿名內部類,但是不是必須的我們一般寫的都是該接口的子接口的實現類,MethodInterceptor*/Producer producerProxy = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {/*** 執行被代理對象的任何方法都會經過該方法, 具有攔截作用** @param proxy* @param method* @param args 以上是哪個參數和基于接口的動態代理中的invoke方法的參數是一樣的* @param methodProxy 當前執行方法的代理對象* @return* @throws Throwable*/public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object returnValue = null;Float money = (Float) args[0];if ("saleProduct".equals(method.getName())) {returnValue = method.invoke(producer, money * 0.8f);}else {returnValue = method.invoke(producer, money * 0.08f);}return returnValue;}});producerProxy.saleProduct(10000f);producerProxy.afterServer(1000f);} }
Producer
package com.itheima.cglib;public class Producer {/*** 銷售** @param money*/public void saleProduct(float money) {System.out.println("拿到錢,賣出產品"+money);}/*** 售后** @param money*/public void afterServer(float money) {System.out.println("提供售后服務,并拿到錢"+money);} }
結果
拿到錢,賣出產品8000.0 提供售后服務,并拿到錢80.0

以上就是動態代理的兩種實現。

我們用上邊的做法去實現目標方法的增強,實現代碼的解耦,是沒有問題的,但是還是需要自己去生成代理對象,自己手寫攔截器,在攔截器里自己手動的去把要增強的內容和目標方法結合起來,這用起來還是有點繁瑣,有更好的解決方案嗎?

答案是:有的!那就是Spring的AOP,這才是咱們最終想引出來的重點!

有了Spring的AOP后,就不用自己去寫了,只需要在配置文件里進行配置,配置好后Spring按照你的配置去幫你生成代理對象,按照你的配置把增強的內容和目標方法結合起來。就相當于自己寫代碼也能實現和aop類似的功能,但是有了Spring aop以后有些事情Spring幫你做了,而且人家Spring做成了可配置化,用起來非常簡單而且很靈活

咱們上邊用的JDK動態代理和cglib動態代理,這兩種在Spring的AOP里都有用到,Spring是根據不同的情況去決定是使用JDK的動態代理生成代理對象,還是使用cglib去生成代理對象。

總結

以上是生活随笔為你收集整理的动态代理JDK于cglib的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。