Java代理相關:JDK動態代理、CGLIB動態代理 原

代理的三種方式:JDK靜態代理、JDK動態代理、CGLIB動態代理

代理(Proxy)是一種設計模式,提供了對目標對象另外的一種訪問方式。可以在目標對象實現的基礎上,增加額外的功能操作,即擴展目標對象的功能。

其實就類似於Python中的註解。

java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。

而cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。

  1. 如果目標對象實現了接口,默認情況下會採用JDK的動態代理實現AOP
  2. 如果目標對象實現了接口,可以強制使用CGLIB實現AOP
  3. 如果目標對象沒有實現了接口,必須採用CGLIB庫,spring會自動在JDK動態代理和CGLIB之間轉換

基礎類

接口

/**
 * @author lpe234
 * @datetime 2018/7/7 10:44
 */
public interface Person {
    void sayHello();
}

實現類

/**
 * @author lpe234
 * @datetime 2018/7/7 10:45
 */
public class Jim implements Person {

    @Override
    public void sayHello() {
        System.out.println("hello world");
    }
}

JDK靜態代理

只能實現對“特定接口的實現類”進行代理。

/**
 * 靜態代理
 *
 * @author lpe234
 * @datetime 2018/7/7 10:49
 */
public class Proxy implements Person {

    private Person person;

    public Proxy(Person person) {
        this.person = person;
    }

    @Override
    public void sayHello() {
        System.out.println("invoke before .......");
        person.sayHello();
        System.out.println("invoke after .......");
    }
}

JDK動態代理

可以實現對多種類的代理。

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

/**
 * @author lpe234
 * @datetime 2018/7/7 10:53
 */
public class ProxyJdk implements InvocationHandler {

    private Object object;

    public Object getInstance(Object object) {
        this.object = object;
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("invoke before .......");
        method.invoke(object, args);
        System.out.println("invoke after .......");
        return null;
    }
}

CGLIB動態代理

CGLIB(Code Generation Library)是一個開源項目。CGLIB可以在運行時動態生成字節碼。 可代理任意一個目標類,但對final類和方法無法代理。

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.7</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @author lpe234
 * @datetime 2018/7/7 11:01
 */
public class ProxyCglib implements MethodInterceptor {
    private Object object;

    public Object getInstance(Object object) {
        this.object = object;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("invoke before .......");
        method.invoke(this.object, objects);
        System.out.println("invoke after .......");
        return null;
    }
}

運行

/**
 * @author lpe234
 * @datetime 2018/7/7 10:44
 */
public class Main {

    public static void main(String[] args) {

        System.out.println("靜態代理");
        Proxy proxy = new Proxy(new Jim());
        proxy.sayHello();

        System.out.println("\n");
        System.out.println("JDK動態代理");
        Person person = (Person) new ProxyJdk().getInstance(new Jim());
        person.sayHello();

        System.out.println("\n");
        System.out.println("Cglib動態代理");
        Person person1 = (Person) new ProxyCglib().getInstance(new Jim());
        person1.sayHello();
    }
}

運行結果:

靜態代理
invoke before .......
hello world
invoke after .......


JDK動態代理
invoke before .......
hello world
invoke after .......


Cglib動態代理
invoke before .......
hello world
invoke after .......

Process finished with exit code 0

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