为什么要用动态代理?静态代理与动态代理详解
代理模式:
代理模式在Java中特別常見,如spring AOP功能就是用代理來實現的。代理模式作用是:在不修改被代理對象功能的基礎上,通過對代理類進行擴展,進行一些功能上的附加與增強。
一般使用代理模式我們需要先定義一個接口,靜態代理只是一種簡單的java代碼功能擴展。而動態代理利用了反射機制,使用更簡單,但背后邏輯…先說明一點,動態代理代理的是接口,而不是類,Proxy類產生的代理對象是Proxy的一個實例,這個實例實現了我們定義的接口
靜態代理:
舉一個黃牛代理買票的例子:
public interface BuyTicket {//買票void buyTicket(); }我自己買票,買不到
public class CommonPerson implements BuyTicket {@Overridepublic void buyTicket() {System.out.println("我自己在12306買不到票!");} }我在智行火車票上加錢搶票,找黃牛代理
public class HuangNiu implements BuyTicket {//我買不到票,我需要被代理CommonPerson person = new CommonPerson();@Overridepublic void buyTicket() {person.buyTicket();System.out.println("我是黃牛,買票找我,出票成功!");}public static void main(String[] args) {HuangNiu huangNiu = new HuangNiu();huangNiu.buyTicket();} }打印結果:
可以看出,我們自己買不到票,找黃牛代理,代理類可以幫助我們實現功能增強。
動態代理(jdk):
動態代理通過java反射機制,獲取某個被代理類的所有接口,并創建代理類。接口類和被代理類同上:
import Proxy.BuyTicket; import Proxy.CommonPerson;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;/*** Description:* Created by CWG on 2020/8/29 10:34*/ public class HuangNiu implements InvocationHandler {private CommonPerson person;public HuangNiu(CommonPerson person) {this.person = person;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object res = method.invoke(person, args);System.out.println("我是黃牛,買票找我,出票成功!");return res;}public static void main(String[] args) {//被代理類CommonPerson person = new CommonPerson();//代理類HuangNiu huangNiu = new HuangNiu(person);//生成代理對象:注意這里生成的代理對象只能是接口BuyTicket buyTicket = (BuyTicket) Proxy.newProxyInstance(CommonPerson.class.getClassLoader(),CommonPerson.class.getInterfaces(),huangNiu);//調用代理對象方法buyTicket.buyTicket();} }打印結果:
可以發現功能與靜態代理一樣,不同的是靜態代理每次都要重寫接口中方法,而動態代理使我們免于去重寫接口中的方法,著重于去擴展相應的功能或是方法的增強,雖然在此示例中可能看不出,可能看上去比靜態代理更復雜,當我們在實際開發環境下,接口中方法很多的時候,就可以發現動態代理的便捷,會大大減少項目中的業務量。
動態代理解讀:
Proxy類
在上例main測試方法中,用到了Proxy.newProxyInstance()方法。動態代理涉及了一個非常重要的類Proxy。正是通過Proxy的靜態方法newProxyInstance才會動態創建代理
public static Object newProxyInstance(ClassLoader var0, Class<?>[] var1, InvocationHandler var2) throws IllegalArgumentException- ClassLoader var0:對應參數 CommonPerson.class.getClassLoader()即被代理類的類加載器
- Class<?>[] var1:對應參數 CommonPerson.class.getInterfaces()即獲取被代理類實現的所有接口
- InvocationHandler var2:對應參數 代理類huangNiu, 為一個InvocationHandler實現對象
InvocationHandler接口
public interface InvocationHandler {Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }代理類需要實現InvocationHandler 接口,invoke()雖然沒有被顯式調用,但該方法也一定被執行了,對應的三個參數分別傳入的是:代理類的實例,method是調用的方法,即需要執行的方法;args是方法的參數;
就本人目前水平,想看懂動態代理背后如何實現有點吃力,以后看懂再接著寫吧,現在也只是知道動態代理是干嘛用的,如果有興趣繼續探究可以參考下面的參考文章3。
參考文章:
1、jdk動態代理與cglib動態代理實現原理
2、為什么要使用java動態代理
3、JDK的動態代理原理
總結
以上是生活随笔為你收集整理的为什么要用动态代理?静态代理与动态代理详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (Integer) 128 == (In
- 下一篇: 查看java源码时出现class文件而不