Java代理模式实现方式与测试方法
·
一、静态代理实现与测试
- 实现方式
静态代理通过手动编写代理类,在编译期确定代理关系,需满足以下步骤: - 定义接口:定义目标对象和代理类共同遵循的接口。
public interface Subject { void request(); } - 实现真实主题类:实现接口并完成核心业务逻辑。
public class RealSubject implements Subject { @Override public void request() { System.out.println("真实主题的请求"); } } - 编写代理类:实现相同接口,并在方法中调用真实对象的方法,添加额外逻辑(如日志、权限校验)。
public class Proxy implements Subject { private RealSubject realSubject; public Proxy() { realSubject = new RealSubject(); } @Override public void request() { preRequest(); // 前置处理(如日志) realSubject.request(); postRequest(); // 后置处理(如清理资源) } private void preRequest() { System.out.println("代理前置处理"); } private void postRequest() { System.out.println("代理后置处理"); } } - 测试方法
通过客户端代码调用代理类的方法,验证额外逻辑是否生效:
public class Client {
public static void main(String[] args) {
Subject proxy = new Proxy();
proxy.request();
}
}
预期输出:
代理前置处理
真实主题的请求
代理后置处理
二、动态代理实现与测试
- JDK动态代理
JDK动态代理基于反射机制,无需手动编写代理类,需实现InvocationHandler接口。
#实现步骤: - 定义接口与实现类:
public interface Subject { void request(); } public class RealSubject implements Subject { @Override public void request() { System.out.println("真实主题的请求"); } } - 实现
InvocationHandler接口:public class DynamicProxyHandler implements InvocationHandler { private Object target; public DynamicProxyHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("动态代理前置处理: " + method.getName()); Object result = method.invoke(target, args); System.out.println("动态代理后置处理: " + method.getName()); return result; } } - 生成代理对象:
public class ProxyFactory { public static Object getProxyInstance(Object target) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new DynamicProxyHandler(target) ); } }
测试方法:
public class Client {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
Subject proxy = (Subject) ProxyFactory.getProxyInstance(realSubject);
proxy.request();
}
}
预期输出:
动态代理前置处理: request
真实主题的请求
动态代理后置处理: request
- CGLIB动态代理
CGLIB通过生成目标类的子类实现代理,无需接口,但需依赖第三方库。
实现步骤:
- 添加CGLIB依赖:
cglib cglib 3.6.1 - 定义非接口类:
public class RealSubject { public void request() { System.out.println("真实主题的请求"); } } - 实现
MethodInterceptor接口:public class CglibProxy implements MethodInterceptor { private Object target; public CglibProxy(Object target) { this.target = target; } public Object getProxy() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("CGLIB前置处理"); Object result = proxy.invokeSuper(obj, args); System.out.println("CGLIB后置处理"); return result; } }
测试方法:
public class Client {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
CglibProxy cglibProxy = new CglibProxy(realSubject);
RealSubject proxy = (RealSubject) cglibProxy.getProxy();
proxy.request();
}
}
预期输出:
CGLIB前置处理
真实主题的请求
CGLIB后置处理
三、实现方式对比与选择
| 类型 | JDK动态代理 | CGLIB动态代理 |
|---|---|---|
| 依赖 | JDK内置,无需额外库 | 需引入CGLIB库 |
| 代理对象 | 接口代理(需目标类实现接口) | 子类代理(无需接口) |
| 性能 | 方法调用稍慢(反射开销) | 方法调用更快(直接调用子类方法) |
| 限制 | 不能代理final类或方法 | 不能代理final类或静态方法 |
四、测试注意事项
- 验证代理逻辑:确保代理方法调用时额外逻辑(如日志、事务)生效。
- 接口一致性:静态代理和JDK动态代理需确保代理类与目标类实现相同接口。
- 性能测试:动态代理在高频调用场景下需评估反射或子类生成的性能影响。
五、总结
静态代理:适用于简单场景,代码可控性强,但需手动维护代理类。
- 动态代理:
- JDK动态代理:适合已实现接口的目标类,代码简洁。
- CGLIB:适合无接口的类,但需注意
final类限制。
根据实际需求选择代理方式,并通过测试验证功能与性能。
更多推荐
所有评论(0)