动态代理

动态代理有哪几种实现方式?

什么是动态代理?

动态代理是一种在运行时动态生成代理对象,并在代理对象上进行方法调用的编程技术。它主要用于在不修改原有代码基础上,增加或改变某些功能的执行流程。动态代理广泛应用于AOP(面向切面编程)、RPC(远程过程调用)、事务管理等领域。在Java中,主要有两种动态代理的实现方式:JDK动态代理和CGLIB动态代理。

JDK动态代理

定义:

JDK动态代理是基于接口的代理技术。它使用 java.lang.reflect.Proxy代理类和
java.lang.reflect.InvocationHandler接口来创建代理对象。当你调用代理对象的任何方法时,调用会被转发到InvocationHandler 的 invoke方法。你可以在这个invoke方法中定义拦截逻辑,比如前置处理、后置处理等。

你的类必须实现一个或多个接口,局限性只能代理接口方法

实现:
  • 定义一个接口及其实现类。

  • 创建一个实现了InvocationHandler接口的类,在该类的invoke方法中定义代理逻辑。

  • 通过[Proxy.nevProxyInstance](//通过 Proxy.newProxyInstance 方法动态创建接口的代理对象
    public static void main(String[] args) {
    // 创建目标对象
    HelloService target = new HelloServiceImpl();
    // 创建调用处理器对象
    HelloServiceHandler handler = new HelloServiceHandler(target);
    // 创建代理对象
    HelloService proxyInstance = (HelloService) Proxy.newProxyInstance(
    target.getClass().getClassLoader(),
    target.getClass().getInterfaces(),
    handler);

    ​ // 通过代理对象调用方法

    ​ proxyInstance.sayHello("World");

    }

    )方法动态创建接口的代理对象。

1.定义一个接口及其实现类

// 定义一个接口
public interface HelloService {
    void sayHello(String name);
}

// 实现该接口的类
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello, " + name);
    }
}

2.创建一个实现了InvocationHandler接口的类

//创建一个实现 InvocationHandler 接口的类
public class HelloServiceHandler implements InvocationHandler {
    //目标对象
    private Object target;

    public HelloServiceHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before sayHello");
        // 执行目标对象的方法
        Object result = method.invoke(target, args);
        System.out.println("After sayHello");
        return result;
    }
}

3.通过 Proxy.newProxyInstance 方法动态创建接口的代理对象

//通过 Proxy.newProxyInstance 方法动态创建接口的代理对象
public static void main(String[] args) {
    // 创建目标对象
    HelloService target = new HelloServiceImpl();
    // 创建调用处理器对象
    HelloServiceHandler handler = new HelloServiceHandler(target);
    // 创建代理对象
    HelloService proxyInstance = (HelloService) Proxy.newProxyInstance(
        target.getClass().getClassLoader(),
        target.getClass().getInterfaces(),
        handler);
    // 通过代理对象调用方法
    proxyInstance.sayHello("World");
}

Cglib动态代理

不需要接口,它是通过继承方式实现代理的

CGLIB底层通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不仅可以代理普通类的方法,还能代理那些没有接口的类的方法。

优点以及缺点:
  • 优点:无需接口实现。在大量调用的场景下,其生成的代理对象在调用时性能比JDK动态代理高
  • 缺点:对final方法无效,需添加额外的依赖。
实现:
  • 创建一个被代理的类
  • 创建一个继承MethodInterceptor的代理类,在intercept方法中定义代理逻辑
  • 使用Enhancer类创建被代理类的子类,并设置回调

1.创建一个被代理的类

//定义一个普通类
public class HelloService {
    public void sayHello(String name) {
        System.out.println("Hello, " + name);
    }
}

2.创建一个继承MethodInterceptor的代理类,在intercept方法中定义代理逻辑

//创建一个继承 MethodInterceptor 的代理类 实现 intercept 方法
public class HelloServiceCglib implements MethodInterceptor {
    private Object target;

    public Object getInstance(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        // 设置回调
        enhancer.setCallback(this);
        // 创建代理对象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before sayHello");
        // 执行目标类的方法
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After sayHello");
        return result;
    }
}

3.实现

//实现
public static void main(String[] args) {
    HelloService target = new HelloService();
    HelloServiceCglib cglib = new HelloServiceCglib();
    HelloService proxy = (HelloService) cglib.getInstance(target);
    proxy.sayHello("World");
}

posted @ 2024-12-01 23:19  wnbzw  阅读(102)  评论(0)    收藏  举报