java动态代理

动态代理是指在程序运行过程中动态地创建代理类和对象的技术。通过动态代理,我们可以在不修改源代码的情况下,在方法执行前后加入一些附加操作,比如日志记录、性能统计、事务管理等。

在 Java 中,动态代理主要有两种实现方式:

  1. 基于接口的动态代理(JDK 动态代理):使用 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来创建代理对象。被代理的类必须实现一个或多个接口。

  2. 基于继承的动态代理(CGLIB 动态代理):使用 CGLIB 库来创建代理对象,无需被代理的类实现接口。

动态代理常用于 AOP(面向切面编程)等方面,它可以帮助我们将与核心业务逻辑相关的横切关注点(如日志记录、事务管理等)与业务逻辑本身分离。这样可以提高代码的模块化程度,使得代码更易于维护和升级。

动态代理是一种在运行时动态生成代理对象的技术,它允许在不修改原始类的情况下,通过代理对象来间接访问原始类的方法。动态代理常用于 AOP(面向切面编程)和基于接口的代理。

基于接口的动态代理(JDK 动态代理)

  1. 基于接口的动态代理(JDK 动态代理):基于 Java 的反射机制,利用 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现动态代理。JDK 动态代理要求被代理的类必须实现一个或多个接口。

下面是一个简单的示例代码,演示如何使用 JDK 动态代理:

java 复制代码
interface Calculator {  
    int add(int a, int b);  
}  
  
class CalculatorImpl implements Calculator {  
    public int add(int a, int b) {  
        return a + b;  
    }  
}  
  
class LoggingInvocationHandler implements InvocationHandler {  
    private Object target;  
  
    public LoggingInvocationHandler(Object target) {  
        this.target = target;  
    }  
  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
        System.out.println("Before invoking method: " + method.getName());  
        Object result = method.invoke(target, args);  
        System.out.println("After invoking method: " + method.getName());  
        return result;  
    }  
}  
  
public class DynamicProxyExample {  
    public static void main(String[] args) {  
        Calculator calculator = new CalculatorImpl();  
        Calculator proxy = (Calculator) Proxy.newProxyInstance(  
                calculator.getClass().getClassLoader(),  
                calculator.getClass().getInterfaces(),  
                new LoggingInvocationHandler(calculator));  
  
        int result = proxy.add(2, 3);  // 这里实际上会调用 LoggingInvocationHandler 中的 invoke 方法  
        System.out.println("Result: " + result);  
    }  
}  

CGLIB

CGLIB(Code Generation Library)是一个强大的基于字节码的代码生成库,它可以在运行时动态地生成新的 class。CGLIB 动态代理是指使用 CGLIB 库来生成代理类,并通过代理类来实现对目标类的代理。

与基于接口的动态代理不同,CGLIB 动态代理可以代理没有实现任何接口的类。它通过生成目标类的子类,并在子类中对目标类的方法进行拦截和增强实现代理功能。

在 CGLIB 动态代理中,代理类的生成过程主要包括以下几个步骤:

  1. 创建 Enhancer 对象:使用 CGLIB 提供的 Enhancer 类创建一个代理类生成器对象。

  2. 设置目标类(被代理类):将目标类设置为 Enhancer 对象的父类,以便生成的代理类成为目标类的子类。

  3. 设置回调函数(Interceptor):使用 Enhancer 对象的 setCallback 方法设置方法拦截器,也就是在代理对象调用方法时的增强逻辑。

  4. 创建代理对象:通过 Enhancer 对象的 create 方法创建代理对象,并将代理对象强制转换为目标类类型。

CGLIB 动态代理的实现原理相对复杂,但它具有很强的灵活性和扩展性,可以代理没有实现接口的类,从而能够对更多类型的类进行代理。它在 Spring 等框架中被广泛应用,用于实现 AOP 功能、对目标类进行增强等方面。

使用 CGLIB 动态代理需要引入 CGLIB 库,并按照以下步骤进行操作:

  1. 引入 CGLIB 库:在 Maven 项目中,在 pom.xml 文件中加入以下依赖:
xml 复制代码
<dependency>  
    <groupId>cglib</groupId>  
    <artifactId>cglib</artifactId>  
    <version>3.3.0</version>    
</dependency>  

或者在 Gradle 项目中,在 build.gradle 文件中加入以下依赖:

groovy 复制代码
dependencies {  
    implementation 'cglib:cglib:3.3.0'  // 替换为最新版本  
}  
  1. 创建目标类:创建一个普通的 Java 类作为被代理的目标类。

  2. 创建拦截器(Interceptor)类:编写一个类来实现对目标类方法的拦截和增强逻辑。

  3. 使用 Enhancer 生成代理对象:使用 CGLIB 的 Enhancer 类来生成代理类,并创建代理对象。

下面是一个简单的示例,演示了如何使用 CGLIB 动态代理:

java 复制代码
import net.sf.cglib.proxy.Enhancer;  
import net.sf.cglib.proxy.MethodInterceptor;  
import net.sf.cglib.proxy.MethodProxy;  
  
import java.lang.reflect.Method;  
  
// 目标类  
class TargetClass {  
    public void doSomething() {  
        System.out.println("TargetClass: Doing something...");  
    }  
}  
  
// 拦截器类  
class MyInterceptor implements MethodInterceptor {  
    @Override  
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
        System.out.println("Before method " + method.getName());  
        Object result = proxy.invokeSuper(obj, args); // 调用目标类的方法  
        System.out.println("After method " + method.getName());  
        return result;  
    }  
}  
  
public class Main {  
    public static void main(String[] args) {  
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(TargetClass.class);  
        enhancer.setCallback(new MyInterceptor());  
  
        TargetClass proxy = (TargetClass) enhancer.create();  
        proxy.doSomething(); // 调用代理对象的方法  
    }  
}  
相关推荐
unclecss1 天前
从 0 到 1 落地 SSE:Spring Boot 3 实战 Server-Sent Events 推送全链路
java·spring boot·后端·http·sse
e***95641 天前
springboot-自定义注解
java·spring boot·spring
stormsha1 天前
Java 设计模式探秘饿汉式与懒汉式单例模式的深度解析
java·单例模式·设计模式·java-ee
稚辉君.MCA_P8_Java1 天前
DeepSeek Java 多线程打印的19种实现方法
java·linux·jvm·后端·架构
白露与泡影1 天前
spring Security 认证流程闭环与调用链路详解
java·后端·spring
i***58671 天前
Java开发的AI应用框架简述——LangChain4j、Spring AI、Agent-Flex
java·人工智能·spring
6***09261 天前
MS SQL Server partition by 函数实战三 成绩排名
java
i***27951 天前
SpringBoot实现异步调用的方法
java·spring boot·spring
d***29241 天前
Springboot中SLF4J详解
java·spring boot·后端
阿在在1 天前
Dubbo 与 Spring 整合全流程解析(含生产者与消费者
java·spring·dubbo