Java动态代理是一种在运行时创建代理对象的技术,它允许开发者在不修改目标类代码的情况下,通过代理类对目标类的实例方法进行增强或拦截。动态代理的核心价值在于能够在程序运行阶段动态地生成一个实现了预定义接口的新类,这个新类就是所谓的“代理类”。
在Java中,有两种主要的实现方式:
JDK动态代理:
CGLIB动态代理:
无论是哪种动态代理方式,其目的都是为了在目标方法执行前后增加额外的行为,或者改变原有的行为,以满足特定的需求,例如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动态代理的基本应用。