Java动态代理是一种在运行时创建代理对象的技术,它允许开发者在不修改目标类代码的情况下,通过代理类对目标类的实例方法进行增强或拦截。动态代理的核心价值在于能够在程序运行阶段动态地生成一个实现了预定义接口的新类,这个新类就是所谓的“代理类”。
在Java中,有两种主要的实现方式:
无论是哪种动态代理方式,其目的都是为了在目标方法执行前后增加额外的行为,或者改变原有的行为,以满足特定的需求,例如AOP(面向切面编程)框架中的事务管理、性能监控、日志记录等功能。
以下是一个简单的JDK动态代理示例,假设我们有一个接口Sellable
和它的实现类RealEstate
。在这个例子中,我们将创建一个动态代理来记录每次调用卖房方法时的日志信息。
首先,定义业务接口:
java 代码解读复制代码// 业务接口:买卖物品
public interface Sellable {
void sell(String item);
void buy(String item);
}
然后,实现这个接口的实体类:
java 代码解读复制代码// 接口的实现类:房地产公司
public class RealEstate implements Sellable {
@Override
public void sell(String item) {
System.out.println("实际销售房源: " + item);
}
@Override
public void buy(String item) {
System.out.println("实际购买房源: " + item);
}
}
接下来,创建一个InvocationHandler实现类,用于处理对代理对象方法的调用:
java 代码解读复制代码import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class LoggingInvocationHandler implements InvocationHandler {
// 被代理的对象引用
private final Sellable target;
public LoggingInvocationHandler(Sellable target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 方法调用前的操作:记录日志
System.out.println("开始销售房源操作...");
// 调用目标对象的方法,并返回结果
Object result = method.invoke(target, args);
// 方法调用后的操作:再次记录日志
System.out.println("完成销售房源操作.");
return result;
}
}
最后,通过Proxy类创建并使用动态代理:
java 代码解读复制代码public class Main {
public static void main(String[] args) {
// 实例化真实对象
Sellable realEstate = new RealEstate();
// 创建代理对象,并将真实对象传给InvocationHandler
// 这块代码是动态代理的精髓
Sellable proxy = (Sellable) Proxy.newProxyInstance(
Sellable.class.getClassLoader(),
new Class<?>[]{Sellable.class},
new LoggingInvocationHandler(realEstate)
);
// 现在调用的是代理对象的方法,但会触发InvocationHandler的逻辑
proxy.sell("豪华别墅");
proxy.buy("大平层");
// 输出:
// 开始销售房源操作...
// 实际销售房源: 豪华别墅
// 完成销售房源操作.
}
}
在这个例子中,当客户端代码通过代理对象调用sell
方法时,实际上会执行LoggingInvocationHandler
中的invoke
方法,在该方法内部先进行日志记录,然后调用实际对象的方法完成销售动作,最后再记录一次日志。这就是JDK动态代理的基本应用。
这种简化方式确实可以在某些场景下直接满足需求,例如在业务逻辑相对简单、需要增强的功能点不多的情况下,其实这种方式就是静态代理。但是动态代理技术的设计初衷和优势在于:
因此,虽然表面上看动态代理可能会显得比直接调用方法更为复杂,但在实际项目开发中,它为解决特定问题提供了强大且灵活的支持,尤其在大型、复杂的软件系统中具有很高的价值。
CGLIB(Code Generation Library)是一个强大的高性能的代码生成库,它广泛应用于Java的动态代理实现中,特别是在Spring AOP框架中作为JDK动态代理的一种补充或替代方案。CGLIB通过字节码技术(Bytecode Engineering Library, BCEL 或者 ASM 库)在运行时对目标类生成一个子类,并覆盖其中非final和非private的方法来创建代理对象。
在Spring框架中,当配置了proxy-target-class属性为true时,Spring会自动选择CGLIB作为代理机制来为目标类创建代理实例。
以下是一个使用CGLIB库进行动态代理的简单示例,假设我们有一个Calculator
类,现在希望通过CGLib创建一个代理类来增强其方法调用:
首先,定义原始的业务类:
java 代码解读复制代码public class Calculator {
public int add(int i, int j) {
System.out.println("Executing original add method.");
return i + j;
}
}
然后,实现CGLIB的MethodInterceptor接口以提供增强逻辑:
java 代码解读复制代码import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class LoggingInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 在方法调用前打印日志
System.out.println("Before calling " + method.getName() + " with arguments: " + Arrays.toString(args));
// 调用实际方法并获取结果
Object result = proxy.invokeSuper(obj, args);
// 在方法调用后打印日志
System.out.println("After calling " + method.getName() + ", result is: " + result);
return result;
}
}
接下来,使用CGLIB的Enhancer类生成代理对象:
java 代码解读复制代码import net.sf.cglib.core.NamingPolicy;
import net.sf.cglib.core.DefaultNamingPolicy;
import net.sf.cglib.proxy.Enhancer;
public class CglibDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Calculator.class); // 设置要代理的目标类
// 设置拦截器(MethodInterceptor)
enhancer.setCallback(new LoggingInterceptor());
// 可选:设置命名策略,避免代理类名称冲突
enhancer.setNamingPolicy(DefaultNamingPolicy.INSTANCE);
// 创建并获取代理对象
Calculator calculatorProxy = (Calculator) enhancer.create();
// 通过代理对象调用方法
int sum = calculatorProxy.add(3, 5);
System.out.println("Sum is: " + sum);
}
}
当运行这段代码时,CGLib会动态地为Calculator类生成一个子类作为代理,并在调用add方法前后执行LoggingInterceptor中的intercept方法。因此,输出将包含日志信息以及原方法的结果。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有