java jdk動態代理模式舉例淺析

代理模式概述

代理模式是爲了提供額外或不一樣的操做,而插入的用來替代」實際」對象的對象,這些操做涉及到與」實際」對象的通訊,所以代理一般充當中間人角色。java

java中經常使用的動態代理模式爲jdk動態代理和cglib動態代理。框架

 

反射技術

瞭解動態代理以前,須要先了解一下java中的反射,反射在框架中的應用很是普遍,它可以配置:類的全限定名,方法和參數。在運行時,動態的完成類的初始化,或者反射調用某些方法。ide

咱們能夠經過Class.forName()方法加載類,並用getConstructor方法配置參數。例:測試

object = (goodsServiceImpl)=Class.forName("com.xjx.test.goodsServiceImpl").getConstructor(String.class).newInstance("計算機");

 

1. jdk動態代理舉例

jdk動態代理由java.lang.reflect.*包提供,它必須藉助一個接口才能實現代理。this

咱們舉個例子來實現jdk動態代理並簡要分析:spa

首先咱們定義一個接口:代理

public interface jdkProxy { public void test(String tString); }

以及它的實現類:code

public class jdkProxyImpl implements jdkProxy{ @Override public void test(String tString) { // TODO Auto-generated method stub
        System.out.println("代理內方法"+tString); } }

接下來咱們要進行代理。代理過程分2步:對象

1.創建起代理對象和真實服務對象之間的關係,生產代理對象;blog

2.實現邏輯的代理;

在jdk動態代理中,要實現代理邏輯就必須實現InvocationHandler接口。它裏面定義了一個invoke方法,每當咱們經過代理對象調用方法時,它都會被轉發到這個invoke方法,咱們來

定義一個實現代理邏輯的類:

public class jdkProxyExample implements InvocationHandler{ //真實對象
    private Object target = null; /** * 創建真實對象和代理對象的代理關係 * @param target真實對象 * @return 代理對象 */
    public Object setTargetAndBind(Object target) { this.target = target; /** * 參數1:getClassLoader()提供類加載器;
      參數2:getInterfaces()要掛載動態代理對象的接口,就是target的接口;
*/ return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this); } /** * 代理方法邏輯 * @param:代理對象 * method:當前調度方法 * args:當前方法參數 * return 代理結果返回 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("進入代理對象方法,在此執行代理對象以前的一些操做"); //執行目標對象中的某個方法 Object object = method.invoke(target, args); System.out.println("調用代理對象方法以後的操做"); return object; } }
1.1 生成一個代理對象

setTargetAndBind()這個方法內的newProxyInstance()方法經過傳入被代理內,再經過反射,生成一個代理類。

1.2 實現代理類的邏輯方法

object obj = method.invoke(target,args),這個方法至關於調度真實對象的方法,只不過是經過反射區實現。它返回方法的執行結果。

而且在invoke方法裏,能夠在調用真實對象方法以前和以後作一些其餘的操做,這也是AOP的實現原理

 

這樣,一個jdk動態代理就完成了,接下來能夠寫個測試類測試一下:

 

public class jdkProxyExampleTest {

    @Test
    public void testProxy() {
        jdkProxyExample jdkProxyExample = new jdkProxyExample();
        //綁定關係,此時jdkProxy已是一個代理對象
        jdkProxy jdkProxy = (jdkProxy)jdkProxyExample.setTargetAndBind(new jdkProxyImpl());
        //執行代理對象方法
        jdkProxy.test("動態代理jdk");
    }
}

 

打印結果以下:

 

2. 爲何jdk動態代理必定須要目標對象實現接口?(可能有誤

1.咱們能夠看到,在綁定關係的方法中,實現被代理類的反射,須要咱們提供接口,而後它經過接口實現代理類。沒有它就找不到反射的方法。

2.因爲java的單繼承機制:首先jdk動態代理是經過newInstance動態的生成代理對象的,newInstance經過ProxyGenerator生成的字節碼錶明的類繼承了Proxy類:

public final class $Proxy0 extends Proxy
  implements jdkProxy{
    ...
}
$Proxy0這個類經過反編譯得到,它就是jdkProxy的實現類的動態的代理類。
因爲java的單繼承機制,被代理對象不能再被其餘的類繼承,那麼咱們若是想創建代理類和被代理類之間的關係,只能經過實現同一個接口了。
相關文章
相關標籤/搜索