java 動態代理(模式) InvocationHandler(為類中方法執行前或后添加內容)


動態代理屬於Java反射的一種。

當我們得到一個對象,想動態的為其一些方法每次被調用前后追加一些操作時,我們將會用到java動態代理。

下邊上代碼:

首先定義一個接口:

package com.liuyx;

public interface Itf {
    public abstract void printMe();

    public abstract void printSth(String me);
}

 

接着是它的實現:

package com.liuyx;

public class Cls implements Itf {

    @Override
    public void printMe() {
        System.out.println("I'm Cls!");
    }

    @Override
    public void printSth(String str) {
        System.out.println(str);
    }

}

 

我們的目的就是通過動態代理技術,在Cls這個類的對象的兩個方法執行前后,加上一些打印操作。

 

現在我們實現一個InvocationHandler,把我們想要通過代理者被代理者追加的操作都寫在invoke方法里面:

package com.liuyx;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class StandardInvocation implements InvocationHandler {

    private Object obj;
    
    StandardInvocation(Object obj){
        this.obj=obj;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before method excute!");
        Object result = method.invoke(obj, args);
        System.out.println("after method excute!");
        return result;
    }

}

首先、這里面有一個obj,這個obj是必須的,我們既然要做代理,我們必須知道我們是給誰做代理,這里的obj就是被代理者。

動態代理說到底也是代理,代理模式里就要求有一個被代理者。

然后是invoke的三個參數、第一個參數就是代理者,如果你想對代理者做一些操作可以使用這個參數;第二個就是被執行的方法,第三個是執行該方法所需的參數。

當你執行代理者的某個方法的時候,最后跑的都是invoke方法。

 

然后是用法:

    public static void main(String[] args) {
        //創建一個被代理者
        Cls c = new Cls();
        //創建一個InvocationHandler,描述我們希望代理者執行哪些操作
        InvocationHandler i = new StandardInvocation(c);
        //通過剛才創建的InvocationHandler,創建真正的代理者。第一個參數是類加載器,第二個參數是這個代理者實現哪些接口
        Itf pxy = (Itf) Proxy.newProxyInstance(Cls.class.getClassLoader(), new Class[] { Itf.class }, i);
        pxy.printSth("Hi");
    }

pxy就是c的代理者。

 

最后來一個稍微改進的寫法:

package com.liuyx;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class InvocationHandlerTest implements InvocationHandler {

    private Object target;

    Object bind(Object i) {
        target = i;
        Object warpedItf;
        warpedItf = Proxy.newProxyInstance(target.getClass().getClassLoader(), i.getClass().getInterfaces(), this);
        return warpedItf;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before method excute!");
        method.invoke(target, args);
        System.out.println("after method excute!");
        return null;
    }
    
    public static void main(String[] args) {
        Cls c = new Cls();
        InvocationHandlerTest pxy = new InvocationHandlerTest();
        Itf itf = (Itf)pxy.bind(c);
        itf.printSth("Hello");
    }

}

 

 

 

 

 

 

 

java動態代理有一定局限性,需要定義至少一個接口,使用cglib則不必如此。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM