Java 動態代理 使用

文章目錄

1. JDK

JDK動態代理必須提供接口才可代理

public interface HelloService {
    void sayHello1(String name);
    String sayHello2(String name);
}
public class HelloServiceImpl implements HelloService {

    @Override
    public void sayHello1(String name) {
        System.out.println("hello1 " + name);
    }

    @Override
    public String sayHello2(String name) {
        System.out.println("hello2 " + name);
        return  name;
    }
}

代理對象實現 InvocationHandler 方法

public class JdkProxy implements InvocationHandler {

    // 被代理對象
    private Object target = null;

    /**
     * 創建代理對象
     * @param target
     * @return
     */
    public Object bind(Object target) {
        this.target = target;
        // 參數爲:target 類加載器;target 的方法;實現 InvocationHandler 接口的邏輯代理類,即當前類
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /**
     * 代理對象調用方法
     * @param proxy 代理對象
     * @param method 方法
     * @param args 方法參數
     * @return 代理調用方法結果
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理前");
        // 調用方法,參數是target不是proxy,因爲target中才有具體的方法實現,proxy中沒有
        Object obj = method.invoke(target,args);
        System.out.println("代理後");
        return obj;
    }
}

JDK動態代理測試:

@Test
public void jdkProxyTest(){
    JdkProxy jdkProxy = new JdkProxy();
    // 創建代理對象
    HelloService proxy = (HelloService)jdkProxy.bind(new HelloServiceImpl());

    // 調用方法
    proxy.sayHello1("jdk1");
    String sayHello2Return = proxy.sayHello2("jdk2");
    System.out.println("sayHello2Return " + sayHello2Return);
}

測試結果:

代理前
hello1 jdk1
代理後
代理前
hello2 jdk2
代理後
sayHello2Return jdk2

2. CGLIB

CGLIB動態代理只需要非抽象類即可代理

public class HelloServiceImpl {

    public void sayHello1(String name) {
        System.out.println("hello1 " + name);
    }

    public String sayHello2(String name) {
        System.out.println("hello2 " + name);
        return  name;
    }
}

代理對象實現 MethodInterceptor 接口

public class CglibProxy implements MethodInterceptor {

    /**
     * 生成cglib代理對象
     * @param cls
     * @return
     */
    public Object getProxy(Class cls){
        // cglib 增強類對象
        Enhancer enhancer = new Enhancer();
        // 設置增強類型
        enhancer.setSuperclass(cls);
        // 定義代理邏輯對象,即實現 MethodInterceptor 接口的對象
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /**
     * 代理邏輯方法
     * @param o 代理對象
     * @param method 方法
     * @param objects 方法參數
     * @param methodProxy 方法代理
     * @return 代理邏輯返回
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理前");
        Object returnObj = methodProxy.invokeSuper(o, objects);
        System.out.println("代理後");
        return returnObj;
    }
}

CGLIB動態代理測試:

@Test
public void cglibProxyTest(){
    CglibProxy cglibProxy = new CglibProxy();
    HelloServiceImpl helloServiceImpl = (HelloServiceImpl) cglibProxy.getProxy(HelloServiceImpl.class);

    helloServiceImpl.sayHello1("cglib");
    String returnObj = helloServiceImpl.sayHello2("cglib");
    System.out.println(returnObj);
}

測試結果:

代理前
hello1 cglib
代理後
代理前
hello2 cglib
代理後
cglib

參考:
你真的完全瞭解Java動態代理嗎?看這篇就夠了
Java 動態代理詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章