jdk動態代理為什麼要使用接口,而不是使用繼承

2020-09-05 35歲碼農

最近面試當時問到了Spring AOP的實現方式,然後就問到了jdk動態代理為什麼使用接口而不是使用繼承,當時一時沒轉過彎來,後來自己回來看了一下原來如此,面試有時就是這樣問題不難,但就是可能想不到這個點去回答。

分析

動態代理是使用反射和字節碼的技術,在運行期創建指定接口和類的子類以及其實例對象的技術,通過動態代理可以對代碼進行增強。java動態代理主要有兩種形式:JDK原生的動態代理和CGLIB動態代理。

首先定義一個接口,上面也提到了要使用接口而不是繼承,使用接口就是在使用生成代理類提供方法的模板。

然後實現接口,這個是具體的一個實現了,我們就是要增強這個實現類的方法。

InvocationHandler是由代理實例的調用處理程序實現的接口。每當調用代理實例的時候就會調用InvocationHandler的invoke方法。

測試,Proxy提供了創建動態代理類和實例的靜態方法,它也是由這些方法創建的所有動態代理類的超類。這裡為什麼要使傳入classLoader主要是運行時動態生成字節碼,然後需要classLoader加載這個類,最終通過反射類實例生成代理類的實例。傳入接口UserServive是為了給生成代理類提供方法的模板。

接下來,我們生成一個代理類,我們可以看到生成的代理類其實是繼承了Proxy,而java是單繼承多實現的。


總結

我們都知道java是單繼承多實現的,因為生成的代理實例已經需要頂級父類Proxy了,如果你在定義成父類顯然是違背了這個原則,所以jdk動態代理一般都是先定義接口,可能你會使用動態代理,但不一定會注意這個問題。

相關焦點

  • java動態代理為什麼需要基於接口
    面試的時候,常常面試官會問spring 的aop底層原理,而aop的底層原理就是動態代理,每個java程式設計師基本都能耳熟能詳,對jdk動態代理和cglib動態代理的區別也瞭然於胸,jdk動態代理只能基於接口,而cglib並不需要。
  • 聊聊JDK和CGLIB動態代理的原理和區別
    2、CGLIB動態代理利用ASM開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。3、何時使用JDK還是CGLIB?1)如果目標對象實現了接口,默認情況下會採用JDK的動態代理實現AOP。2)如果目標對象實現了接口,可以強制使用CGLIB實現AOP。
  • 你必須會的 JDK 動態代理和 CGLIB 動態代理
    我們在閱讀一些 Java 框架的源碼時,基本上常會看到使用動態代理機制,它可以無感的對既有代碼進行方法的增強,使得代碼擁有更好的拓展性。 通過從靜態代理、JDK 動態代理、CGLIB 動態代理來進行本文的分析。
  • 終於搞懂靜態代理、JDK和CGLIB動態代理,面試再也不慌了
    代理實現方式: 靜態代理:代理和被代理對象在代理之前是確定的,他們都實現相同的接口或者繼承相同的抽象類靜態代理實現方式: 繼承代理:通過繼承需要代理的類,在子類調用父類,在調用前後記錄日誌public class
  • Java中的原生動態代理和CGLIB動態代理的原理
    :JDK原生動態代理和CGLIB動態代理。,但Java動態代理是基於接口的,如果對象沒有實現接口我們該如何代理呢?CGLIB通過繼承方式實現代理。然後在需要使用HelloConcrete的時候,通過CGLIB動態代理獲取代理對象。
  • Spring AOP --JDK動態代理方式
    我們知道Spring是通過JDK或者CGLib實現動態代理的,今天我們討論一下JDK實現動態代理的原理。一、簡述Spring在解析Bean的定義之後會將Bean的定義生成一個BeanDefinition對象並且由BeanDefinitionHolder對象持有。
  • 這些JDK 動態代理的面試點你一定要知道
    static Class getProxyClass (ClassLoaderloader, Class[] interfaces)3、返回代理類的一個實例,返回後的代理類可以當作被代理類使用(可使用被代理類的在Subject接口中聲明過的方法):static
  • 那這些JDK動態代理的面試點你一定要知道
    static Class getProxyClass (ClassLoaderloader, Class[] interfaces)3、返回代理類的一個實例,返回後的代理類可以當作被代理類使用(可使用被代理類的在Subject接口中聲明過的方法):static
  • JDK動態代理實現方案
    ); //如果以接口的方式代理對象 if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !
  • cglib動態代理對類沒有任何限制嗎?
    大家都知道,動態代理常見的兩種實現方式,jdk的動態代理和cglib動態代理,而jdk動態代理必須基於接口,cglib沒有這樣的要求。之前我們討論過jdk動態代理為什麼必須基於接口,傳送門:那麼cglib動態代理真的沒有任何限制嗎?
  • 在debug模式下,用影音與動圖學習靜態代理與jdk代理
    而jdk動態代理就和這個實現原理大概一致。從上面的debug視頻中,可以看出JDK 動態代理,其實就是實現 InvocationHandler 接口,重寫 invoke 方法,添加業務邏輯。Proxy和InvocationHandler大家都知道Spring是面向切面編程,而JDK動態代理是面向接口的代理模式,JDK動態代理通過InvocationHandler是一個接口,可以通過實現該接口定義橫切邏輯,並通過反射機制調用目標類的代碼
  • 面試必問的動態代理,我們來看看它們的源碼
    因此我們需要一個動態的代理類,這個代理類並不是一開始就創建的,而是在調用的時候創建。Java中的動態代理有動態代理和動態代理,這兩種動態代理在Spring的代理模式中有用到。Spring中這兩種動態代理的區別為:「(1)當目標對象實現了接口,默認使用JDK動態代理,也可以強制使用CGLIB動態代理。(2)當目標對象沒有實現接口,必須使用CGLIB動態代理。
  • 反編譯看JDK的動態代理原理
    經常聽到動態代理,總是覺得是很複雜的東西,今天通過設置特殊參數輕鬆理解動態代理。代碼實現目標方法與代理類代碼如下圖:這裡為了展示把三個類放到一個文件中,首先是一個接口包含一個getName方法,然後是被代理類,它實現了這個接口。
  • 趣味設計模式系列:代理模式JDK動態代理源碼解析,一文便知
    Proxy源碼分析上一篇,在使用JDK動態代理的時候,藉助於Proxy類,使用newProxyInstance靜態方法,創建了動態代理對象,這個方法接收三個參數,分別是目標類的類加載器、目標類實現的接口數組、自定義的InvocationHandler
  • 如何使用動態代理,自己寫一個資料庫連接池?
    ①實現DataSource接口dataSource是Java中的一個接口,也是Java制定的一個規範,不同的連接池都需要實現這個接口。MyDataSource是我們自定義的一個連接池,自然也是需要實現該接口。②創建連接池容器為什麼要用LindkedList?連接池中的連接被取走,相當於刪除了該連接。
  • JDK和CGLIB生成動態代理類的區別
    其中動態代理又可分為:JDK動態代理和CGLIB代理。代理模式在實際使用時需要指定具體的目標對象,如果為每個類都添加一個代理類的話,會導致類很多,同時如果不知道具體類的話,怎樣實現代理模式呢?這就引出動態代理。JDK動態代理只能針對實現了接口的類生成代理。
  • 為什麼Java類不支持多繼承而接口可以?
    每個用Java的人都知道java不支持多繼承,但為什麼呢?無論從抽象還是多態等層面思考,感覺都是行得通的,那麼為什麼不支持呢?」主要就是說,Gosling認為,多繼承是一種很少使用,並且很容易混淆的特性,所以Java語言就像刪除操作符重載特性一樣刪除了多繼承這種特性。也就是說java為了便於程式設計師理解和使用,去除了一些不容易理解的特性,例如類的多繼承。並非不能實現。那為什麼接口可以呢?
  • 為什麼要使用動態IP代理來爬取網站
    如果遇到這種情況,對應小型爬蟲來說,最簡單經濟有效的方式,就是通過代理來反問。這就解釋了為什麼要使用動態IP代理來爬取網站了。下面雲連代理小編帶你來了解一下:為什麼要使用動態IP代理來爬取網站>一、使用動態IP代理的一些基本概念動態IP池其實就是一堆可以用來做代理訪問的Pool,作為Service Provider它對外提供可用的動態IP及埠。
  • 9分鐘帶你搞懂代理模式、靜態代理、JDK+CGLIB動態代理
    JDK 動態代理,我們先來看看 JDK 動態代理的使用。,我們這裡還是簡單介紹一下其使用以及和JDK 動態代理的對比。CGLIB 通過繼承方式實現代理。很多知名的開源框架都使用到了CGLIB[5], 例如 Spring 中的 AOP 模塊中:如果目標對象實現了接口,則默認採用 JDK 動態代理,否則採用 CGLIB 動態代理。
  • JDK動態代理詳解
    JDK動態代理是代理模式的一種,且只能代理接口。spring也有動態代理,稱為CGLib,現在主要來看一下JDK動態代理是如何實現的?一、介紹JDK動態代理是有JDK提供的工具類Proxy實現的,動態代理類是在運行時生成指定接口的代理類,每個代理實例(實現需要代理的接口)都有一個關聯的調用處理程序對象