作者:骁炉 | 来源:互联网 | 2024-12-04 19:46
Java 动态代理详解与示例
在Java中,动态代理是一种强大的编程技术,允许程序在运行时创建符合已知接口的代理类。这种机制常用于AOP(面向切面编程)、事务管理等场景。本文将通过一个具体的例子来展示如何使用Java的动态代理。
1. 定义接口
package com.bors.proxy;
public interface Person {
void findPartner();
}
这里定义了一个名为Person的接口,其中包含一个方法findPartner(),表示寻找伴侣的行为。
2. 实现接口
package com.bors.proxy;
public class XiaoMing implements Person {
// 婚前,需要父母帮助寻找伴侣
@Override
public void findPartner() {
System.out.println("我是小明,我现在单身,希望能找到一位合适的伴侣。");
}
// 婚后,需要父母帮助照顾孩子
}
在这个实现类XiaoMing中,我们重写了findPartner()方法,模拟了小明在婚前希望找到伴侣的愿望。
3. 创建代理处理器
package com.bors.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ParentHandler implements InvocationHandler {
private final Person person;
public ParentHandler(Person person) {
this.person = person;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeAction();
Object result = method.invoke(person, args);
afterAction();
return result;
}
private void beforeAction() {
System.out.println("我们是小明的父母,我们将帮助小明寻找合适的伴侣。");
}
private void afterAction() {
System.out.println("我们是小明的父母,我们将在小明结婚后帮助他照顾孩子。");
}
}
这个代理处理器类ParentHandler实现了InvocationHandler接口,并重写了invoke方法。在这个方法中,我们可以在目标方法调用前后添加额外的操作,如打印日志或进行权限检查。
4. 测试动态代理
public class DynamicProxyTest {
@Test
public void testDynamicProxy() {
// 创建目标对象
Person target = new XiaoMing();
// 创建代理对象
Person proxy = (Person) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new ParentHandler(target)
);
// 调用代理对象的方法
proxy.findPartner();
}
}
在测试类DynamicProxyTest中,我们首先创建了目标对象XiaoMing,然后通过Proxy类的newProxyInstance方法创建了一个代理对象。最后,我们通过代理对象调用了findPartner方法,观察到代理处理器中的beforeAction和afterAction方法也被正确调用。
5. 代理类的生成
当使用Proxy.newProxyInstance方法创建代理对象时,JVM会自动生成一个代理类,该类实现了指定的所有接口,并且继承了Proxy类。这个代理类通常以$Proxy开头,例如$Proxy2。
public final class $Proxy2 extends Proxy implements Person {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy2(InvocationHandler handler) {
super(handler);
}
public final boolean equals(Object obj) {
try {
return (Boolean) super.h.invoke(this, m1, new Object[]{obj});
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final String toString() {
try {
return (String) super.h.invoke(this, m2, null);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final void findPartner() {
try {
super.h.invoke(this, m3, null);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
public final int hashCode() {
try {
return (Integer) super.h.invoke(this, m0, null);
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.bors.proxy.Person").getMethod("findPartner");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException | ClassNotFoundException e) {
throw new ExceptionInInitializerError(e);
}
}
}
这个代理类$Proxy2包含了对Person接口中所有方法的实现,每个方法内部都调用了InvocationHandler的invoke方法来执行实际的逻辑。