Java动态代理详解

文章目录

Java中的动态代理是一种设计模式,它允许在运行时创建代理对象,而不是在编译时。代理对象可以用来代理真实对象的方法调用。

Java中的动态代理主要有两种实现方式:JDK动态代理CGLIB动态代理

一、JDK动态代理

JDK动态代理使用Java标准库中的java.lang.reflect包来创建代理对象。它适用于实现了接口的类,通过接口类型来代理对象。

1、关键类和接口

  • InvocationHandler接口:
    这是一个接口,必须实现其invoke方法,代理对象的所有方法调用都会转发到这个方法。
  • Proxy类:
    这是一个用来创建代理对象的类,提供了静态方法newProxyInstance来生成代理对象。

2、实现步骤

1)定义接口和实现类:

java 复制代码
public interface MyService {
    void perform();
}

public class MyServiceImpl implements MyService {
    @Override
    public void perform() {
        System.out.println("Executing perform method");
    }
}

2)实现InvocationHandler接口,编写代理逻辑

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method invoke");
        Object result = method.invoke(target, args);
        System.out.println("After method invoke");
        return result;
    }
}

3)使用Proxy.newProxyInstance方法创建代理对象

java 复制代码
import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        MyService myService = new MyServiceImpl();
        MyInvocationHandler handler = new MyInvocationHandler(myService);

        MyService proxyInstance = (MyService) Proxy.newProxyInstance(
            myService.getClass().getClassLoader(),
            myService.getClass().getInterfaces(),
            handler
        );

        proxyInstance.perform();
    }
}

二、CGLIB动态代理

CGLIB(Code Generation Library)是一种强大的字节码生成库,它允许在运行时创建子类,适用于没有实现接口的类。CGLIB通过继承被代理类来创建代理对象,因此无法代理final类。

1、关键类

  • Enhancer类:
    这是CGLIB用来生成代理类的主要类,通过设置超类和回调来创建代理对象。
  • MethodInterceptor接口:
    这是一个接口,类似于InvocationHandler,需要实现intercept方法。

2、实现步骤

1)添加CGLIB依赖:

在项目中添加CGLIB库的依赖。对于Maven项目:

xml 复制代码
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

2)定义实现类:定义一个没有实现接口的类

java 复制代码
public class MyService {
    public void perform() {
        System.out.println("Executing perform method");
    }
}

3)实现MethodInterceptor,编写代理逻辑。

java 复制代码
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method invoke");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After method invoke");
        return result;
    }
}

4)使用Enhancer类创建代理对象。

java 复制代码
import net.sf.cglib.proxy.Enhancer;

public class Main {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyService.class);
        enhancer.setCallback(new MyMethodInterceptor());

        MyService proxyInstance = (MyService) enhancer.create();
        proxyInstance.perform();
    }
}

三、总结

  • JDK动态代理:适用于实现了接口的类,通过InvocationHandler处理代理逻辑。
  • CGLIB动态代理:适用于没有实现接口的类,通过继承实现代理,使用MethodInterceptor处理代理逻辑。性能更优。

动态代理在AOP(面向切面编程)、拦截器、权限控制、事务管理等领域有广泛应用,提供了灵活的方式来在运行时增强对象行为。

相关推荐
C++ 老炮儿的技术栈1 分钟前
MFC CPtrArray的用法
开发语言·数据结构·c++·算法·mfc·c
杨运交3 分钟前
[069][公共模块]Spring Boot 全局异常处理与参数校验实战(下):校验异常精细化处理与 WebFlux 适配
java·spring boot·后端
佳児素花痴╮5 分钟前
C++基础速通
开发语言·c++
是立不是利9 分钟前
深入理解JavaScript事件委托
开发语言·前端·javascript
啊阿狸不会拉杆9 分钟前
《计算机网络-自顶向下方法》6.4 交换局域网 读书笔记
开发语言·计算机网络·php
Raas10023 分钟前
MAI Gateway(魔芋企业级AI网关)对比分析:AI网关和OpenRouter区别?企业级能力差距一览
java·服务器·网络·人工智能·gateway·ai网关·mai gateway
心中有你021423 分钟前
Python Tkinter 情侣恋爱日记桌面小程序(本地文件存储,无数据库)
开发语言·python
APItesterCris32 分钟前
告别人工盯品!借助 Open‑Claw 快速搭建电商商品全自动监控与数据分析系统(完整实操代码)
java·大数据·前端·数据库
青山木42 分钟前
Hot 100 --- 跳跃游戏 II
java·数据结构·算法·leetcode·贪心算法
ly768944 分钟前
Spring 中的 @Configuration 与 @Component 差异:为何代理时机决定 Bean 生命周期行为
java·后端·spring·注解·代理·bean生命周期