Java代理相关:JDK动态代理、CGLIB动态代理

时间:2022-07-22
本文章向大家介绍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