资讯动态

Java代理模式深度解析:从基础到高级应用

发布时间:2026/9/10 12:48:38 来源:尧图企业网站定制
1. 代理模式基础概念与核心价值代理模式Proxy Pattern是Java设计模式中结构型模式的典型代表它通过引入代理对象来控制对原始对象的访问。这种模式在Java生态中应用极为广泛从Spring AOP到RPC框架几乎无处不在。1.1 代理模式的三大核心要素代理模式的实现离不开以下三个关键角色Subject抽象主题定义真实主题和代理主题的共同接口使得在任何使用真实主题的地方都可以使用代理主题RealSubject真实主题实现真正的业务逻辑是代理模式最终要引用的对象Proxy代理持有对真实主题的引用控制对真实主题的访问并可以附加额外的操作// 典型代理模式结构示例 interface Subject { void request(); } class RealSubject implements Subject { public void request() { System.out.println(RealSubject handling request); } } class Proxy implements Subject { private RealSubject realSubject; public void request() { if (realSubject null) { realSubject new RealSubject(); } preRequest(); realSubject.request(); postRequest(); } private void preRequest() { /* 前置处理 */ } private void postRequest() { /* 后置处理 */ } }1.2 代理模式的五种典型应用场景远程代理Remote Proxy为位于不同地址空间的对象提供本地代表典型如RPC调用虚拟代理Virtual Proxy延迟创建开销大的对象如图片懒加载保护代理Protection Proxy控制对原始对象的访问权限智能引用代理Smart Reference Proxy在访问对象时执行额外操作如引用计数缓存代理Cache Proxy为开销大的运算结果提供临时存储提示在大厂面试中面试官经常会要求候选人举例说明各种代理类型的实际应用场景。建议准备2-3个自己项目中的真实案例。2. Java代理实现方式深度对比Java中实现代理主要有三种方式每种方式都有其特定的使用场景和优缺点。2.1 静态代理最基础的手工实现静态代理需要手动创建代理类是最直观的实现方式。它的特点包括代理类和被代理类实现相同接口在编译期就已经确定代理关系需要为每个被代理类创建对应的代理类// 静态代理示例 public interface UserService { void addUser(String username); } public class UserServiceImpl implements UserService { public void addUser(String username) { System.out.println(添加用户 username); } } public class UserServiceProxy implements UserService { private UserService target; public UserServiceProxy(UserService target) { this.target target; } public void addUser(String username) { System.out.println(前置处理); target.addUser(username); System.out.println(后置处理); } }静态代理的优缺点分析优点实现简单易于理解编译期检查安全性高缺点会产生大量重复代码接口变更时需要修改所有相关代理类2.2 JDK动态代理基于接口的运行时代理JDK动态代理利用Java反射机制在运行时动态生成代理类。核心要点包括只能代理实现了接口的类通过Proxy类和InvocationHandler接口实现代理类是在运行时动态生成的.class文件// JDK动态代理示例 public class LogInvocationHandler implements InvocationHandler { private Object target; public LogInvocationHandler(Object target) { this.target target; } 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; } } // 使用方式 UserService userService new UserServiceImpl(); UserService proxy (UserService) Proxy.newProxyInstance( UserService.class.getClassLoader(), new Class[]{UserService.class}, new LogInvocationHandler(userService) );JDK动态代理的底层原理通过ProxyGenerator.generateProxyClass()生成代理类的字节码代理类继承Proxy并实现目标接口所有方法调用都会转发到InvocationHandler.invoke()方法2.3 CGLIB动态代理基于继承的字节码增强CGLIB(Code Generation Library)通过继承方式实现代理可以代理没有实现接口的类。关键特性包括通过ASM字节码框架生成子类需要引入cglib依赖不能代理final类和方法// CGLIB代理示例 public class UserServiceInterceptor implements MethodInterceptor { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println(前置处理); Object result proxy.invokeSuper(obj, args); System.out.println(后置处理); return result; } } // 使用方式 Enhancer enhancer new Enhancer(); enhancer.setSuperclass(UserServiceImpl.class); enhancer.setCallback(new UserServiceInterceptor()); UserService proxy (UserService) enhancer.create();CGLIB与JDK动态代理的对比对比维度JDK动态代理CGLIB代理实现机制实现接口继承目标类依赖Java原生支持需要引入第三方库性能调用反射方法较慢直接调用较快限制只能代理接口不能代理final类和方法生成方式运行时生成代理类运行时生成子类方法调用通过InvocationHandler转发通过MethodInterceptor拦截注意在Spring AOP中默认使用JDK动态代理如果目标对象没有实现接口则会自动切换到CGLIB代理。从Spring Boot 2.0开始为了简化配置默认都使用CGLIB代理。3. 代理模式全链路解析与源码剖析理解代理模式的完整实现链路对于深入掌握这一设计模式至关重要。下面我们将从字节码层面分析代理模式的实现原理。3.1 JDK动态代理生成字节码分析通过设置系统属性我们可以将JDK动态代理生成的.class文件保存到磁盘System.setProperty(sun.misc.ProxyGenerator.saveGeneratedFiles, true);生成的代理类大致结构如下public final class $Proxy0 extends Proxy implements UserService { private static Method m1; private static Method m2; private static Method m3; 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.example.UserService).getMethod(addUser, Class.forName(java.lang.String)); } catch (NoSuchMethodException e) { throw new NoSuchMethodError(e.getMessage()); } } public $Proxy0(InvocationHandler var1) { super(var1); } public final void addUser(String var1) { try { super.h.invoke(this, m3, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } // 省略equals、hashCode、toString等方法 }从字节码可以看出代理类继承自Proxy并实现目标接口所有方法调用都通过InvocationHandler转发方法调用使用反射机制这是JDK动态代理性能开销的主要来源3.2 CGLIB代理生成字节码分析CGLIB生成的代理类结构更为复杂核心特点包括继承被代理类通过MethodInterceptor实现方法拦截使用FastClass机制避免反射调用典型的CGLIB代理类结构public class UserServiceImpl$$EnhancerByCGLIB$$12345678 extends UserServiceImpl { private MethodInterceptor interceptor; public final void addUser(String var1) { MethodProxy var2 MethodProxy.create(...); this.interceptor.intercept(this, ReflectUtils.findDeclaredMethod(UserServiceImpl.class, addUser, String.class), new Object[]{var1}, var2); } // 生成的FastClass避免反射调用 public Object invoke(int methodIndex, Object obj, Object[] args) { switch(methodIndex) { case 0: ((UserServiceImpl)obj).addUser((String)args[0]); return null; // 其他方法... } } }3.3 代理模式在Spring中的应用Spring框架中代理模式的应用随处可见最典型的就是AOP的实现。Spring AOP的代理创建流程如下代理创建决策检查目标类是否实现接口 → 选择JDK动态代理未实现接口或配置强制使用CGLIB → 选择CGLIB代理代理创建过程// AbstractAutoProxyCreator.createProxy() protected Object createProxy(Class? beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory new ProxyFactory(); // 配置代理设置... // 添加增强(Advice) Advisor[] advisors buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); // 设置目标源 proxyFactory.setTargetSource(targetSource); // 定制代理... return proxyFactory.getProxy(getProxyClassLoader()); }方法调用链JDK代理Proxy → InvocationHandler → 目标方法CGLIB代理代理类 → MethodInterceptor → 目标方法重要提示在Spring Boot 2.x之后默认都使用CGLIB代理因为不需要强制实现接口使用更灵活性能优于JDK动态代理特别是高版本CGLIB避免了JDK代理的一些限制如接口方法可见性问题4. 大厂面试高频问题与避坑指南代理模式是Java面试中的高频考点尤其是Spring框架相关岗位。下面整理了大厂面试中最常见的代理模式相关问题及回答技巧。4.1 基础概念类问题问题1说说你对代理模式的理解避坑指南不要只背诵定义要结合具体应用场景区分静态代理和动态代理的适用场景最好能举例说明自己在项目中的实际应用推荐回答结构定义代理模式是通过引入代理对象控制对原始对象访问的结构型设计模式目的解耦客户端与真实对象增加额外功能如日志、事务等分类静态代理、动态代理JDK/CGLIB应用Spring AOP、RPC调用、安全控制等个人经验项目中在XX场景下使用代理模式解决了XX问题问题2JDK动态代理和CGLIB代理有什么区别避坑要点不要只回答一个基于接口一个基于继承要深入底层实现原理和性能差异结合Spring框架的选择策略说明对比维度表维度JDK动态代理CGLIB代理实现机制实现相同接口继承目标类依赖Java原生支持需要第三方库性能调用反射方法较慢直接调用较快限制只能代理接口不能代理final类和方法生成方式ProxyInvocationHandlerEnhancerMethodInterceptorSpring默认选择目标实现接口时目标未实现接口或配置强制CGLIB时4.2 原理深挖类问题问题3JDK动态代理为什么只能基于接口技术要点Java单继承限制代理类已经继承了Proxy类无法再继承其他类类型安全考虑通过接口确保代理类和目标类具有相同的方法签名设计决策保持代理实现的简洁性和一致性扩展回答 Java的单继承特性决定了Proxy类只能通过实现接口的方式来实现代理。从设计上看这种方式虽然有一定限制但保证了类型安全也使得代理逻辑更加清晰。在实际开发中如果遇到必须基于类的代理需求可以考虑切换到CGLIB或者重新设计接口。问题4CGLIB是如何避免使用反射调用的核心原理FastClass机制为每个被代理类生成FastClass通过索引直接调用方法方法签名预编译在生成代理类时就确定方法调用路径字节码优化ASM框架直接操作字节码避免反射开销示例说明 假设我们有一个addUser方法CGLIB会生成两个FastClass一个是针对目标类的通过索引直接调用原始方法一个是针对代理类的通过索引调用拦截器调用时不是通过反射查找方法而是直接根据预定义的索引进行调用这大大提高了性能。4.3 实践应用类问题问题5Spring AOP默认使用哪种代理方式如何强制使用CGLIB配置方式Spring Boot 1.x默认使用JDK动态代理接口时Spring Boot 2.x默认全部使用CGLIB强制使用CGLIBEnableAspectJAutoProxy(proxyTargetClass true)XML配置方式aop:aspectj-autoproxy proxy-target-classtrue/问题6代理模式下this调用会有什么问题如何解决典型问题场景public class UserServiceImpl implements UserService { public void addUser(String username) { this.logOperation(); // 这里this指向的是真实对象不是代理对象 } public void logOperation() { System.out.println(记录操作日志); } }解决方案避免在代理对象方法内部使用this调用其他方法通过AopContext获取当前代理对象需要开启exposeProxyEnableAspectJAutoProxy(exposeProxy true) ((UserService)AopContext.currentProxy()).logOperation();重构代码结构将需要代理的方法拆分到不同类中4.4 高频陷阱与优化策略陷阱1代理导致的equals/hashCode问题问题现象代理对象与真实对象比较时返回false集合操作出现意外行为解决方案在InvocationHandler/MethodInterceptor中统一处理equals和hashCode方法比较时统一使用真实对象进行比较实现自定义的equals和hashCode逻辑陷阱2代理对象序列化问题问题现象JDK动态代理对象序列化失败反序列化后代理功能失效解决方案为InvocationHandler实现Serializable接口确保目标对象也可序列化考虑使用其他序列化方案如JSON性能优化建议对于频繁调用的代理方法考虑使用CGLIB在InvocationHandler/MethodInterceptor中缓存Method对象避免在代理逻辑中进行复杂操作对于固定代理逻辑可以考虑使用静态代理5. 代理模式高级应用与最佳实践掌握了代理模式的基础用法后我们来看一些高级应用场景和行业内的最佳实践。5.1 动态代理在RPC框架中的应用现代RPC框架如Dubbo、gRPC等都大量使用动态代理技术。典型的RPC调用流程客户端通过动态代理创建服务接口的代理对象代理对象将方法调用封装为网络请求服务端接收请求并反射调用真实方法将结果序列化返回给客户端Dubbo中的代理实现示例// 服务引用创建代理 public T T getProxy(InvokerT invoker, Class?[] interfaces) { return (T) Proxy.getProxy(interfaces) .newInstance(new InvokerInvocationHandler(invoker)); } // 方法调用处理 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 构造RPC调用请求 RpcInvocation invocation new RpcInvocation(method, args); // 通过网络发送请求 return invoker.invoke(invocation).recreate(); }优化技巧对基本类型参数使用原生类型避免装箱拆箱缓存方法签名减少反射开销对频繁调用的方法生成专用调用代码5.2 代理模式在MyBatis中的应用MyBatis的Mapper接口也是通过动态代理实现的public class MapperProxyT implements InvocationHandler, Serializable { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 处理Object方法 if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } // 将方法调用转换为SQL执行 MapperMethod mapperMethod cachedMapperMethod(method); return mapperMethod.execute(sqlSession, args); } }关键点每个Mapper接口对应一个代理实例方法调用被转换为SQL命令执行使用缓存避免重复解析SQL5.3 代理模式性能优化实践方案1代理类预生成在应用启动时预生成所有需要的代理类避免运行时生成的开销// Spring中的提前AOP代理初始化 public void preInstantiateSingletons() throws BeansException { // 提前初始化所有单例bean包括生成代理 getBean(beanName); }方案2代理方法缓存缓存Method对象和调用路径避免重复查找public class CachedInvocationHandler implements InvocationHandler { private final Object target; private final MapMethod, MethodHandler methodCache new ConcurrentHashMap(); public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodHandler handler methodCache.computeIfAbsent(method, m - { // 创建优化的方法处理器 return createMethodHandler(m); }); return handler.invoke(args); } }方案3选择性代理只为真正需要代理的方法创建代理逻辑public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 只代理带有特定注解的方法 if (!method.isAnnotationPresent(Transactional.class)) { return method.invoke(target, args); } // 执行代理逻辑... }5.4 代理模式与其它模式的结合代理模式 责任链模式实现多层代理和拦截器链public class ChainInvocationHandler implements InvocationHandler { private final ListInvocationHandler handlers; private final Object target; private int index 0; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (index handlers.size()) { return handlers.get(index).invoke(proxy, method, args); } return method.invoke(target, args); } }代理模式 装饰器模式在代理的基础上增加装饰功能public class DecoratingProxy implements InvocationHandler { private final Object target; private final ListDecorator decorators; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result method.invoke(target, args); for (Decorator decorator : decorators) { result decorator.decorate(result); } return result; } }代理模式 观察者模式在方法调用前后触发事件public class ObservableInvocationHandler implements InvocationHandler { private final Object target; private final ListMethodEventListener listeners; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { notifyBefore(method, args); Object result method.invoke(target, args); notifyAfter(method, args, result); return result; } }6. 常见问题排查与调试技巧在实际开发中使用代理模式时会遇到各种奇怪的问题。下面分享一些常见问题的排查方法和调试技巧。6.1 代理对象识别问题问题现象判断对象是否是代理对象时得到错误结果instanceof操作不符合预期解决方案使用AopUtils工具类判断AopUtils.isAopProxy(object) // 是否是代理对象 AopUtils.isCglibProxy(object) // 是否是CGLIB代理 AopUtils.isJdkDynamicProxy(object) // 是否是JDK代理通过类名判断object.getClass().getName().contains($$EnhancerByCGLIB$$) // CGLIB代理 object.getClass().getName().contains($Proxy) // JDK代理6.2 代理导致的注解失效问题问题现象在代理对象上获取注解得到null注解继承行为不符合预期原因分析默认情况下注解不会被代理类继承需要通过特殊方式获取原始类的注解解决方案使用Spring的AnnotationUtilsAnnotationUtils.findAnnotation(method.getDeclaringClass(), Transactional.class);对于方法注解AnnotationUtils.findAnnotation( AopUtils.getMostSpecificMethod(method, targetClass), Transactional.class);6.3 代理对象调试技巧技巧1查看代理类生成代码对于JDK代理System.setProperty(sun.misc.ProxyGenerator.saveGeneratedFiles, true);对于CGLIB代理System.setProperty(cglib.debugLocation, /tmp/cglib);技巧2使用Arthas诊断代理调用启动Arthasjava -jar arthas-boot.jar查看代理类jad com.example.UserService$$EnhancerByCGLIB$$12345678监控方法调用watch com.example.UserServiceImpl addUser {params,returnObj} -x 3技巧3日志诊断配置在logback-spring.xml中添加logger nameorg.springframework.aop levelDEBUG/ logger nameorg.springframework.beans levelDEBUG/6.4 性能问题排查常见性能瓶颈频繁生成代理类反射调用开销代理逻辑过于复杂优化方案缓存代理对象避免重复创建使用MethodHandle代替反射调用简化代理逻辑将耗时操作异步化诊断工具JProfiler分析代理调用耗时Arthas监控方法调用链路JMH进行基准测试// JMH基准测试示例 BenchmarkMode(Mode.AverageTime) OutputTimeUnit(TimeUnit.MICROSECONDS) public class ProxyBenchmark { private UserService jdkProxy; private UserService cglibProxy; private UserService directCall; Setup public void setup() { // 初始化各种代理... } Benchmark public void testJdkProxy() { jdkProxy.addUser(test); } Benchmark public void testCglibProxy() { cglibProxy.addUser(test); } Benchmark public void testDirectCall() { directCall.addUser(test); } }7. 现代Java中的代理模式演进随着Java语言的不断发展代理模式也在不断演进出现了许多新的实现方式和优化方案。7.1 Java 16的代理模式改进隐藏代理类从Java 16开始JDK动态代理生成的代理类默认是隐藏的需要通过特殊参数开启保存-Djdk.proxy.ProxyGenerator.saveGeneratedFilestrue性能优化代理类生成速度提升方法调用链路优化7.2 基于Lambda的方法句柄代理Java 8引入的MethodHandle和Lambda表达式提供了新的代理实现方式public class LambdaProxyFactory { public static T T createProxy(ClassT interfaceType, Object target) { return (T) Proxy.newProxyInstance( interfaceType.getClassLoader(), new Class?[]{interfaceType}, (proxy, method, args) - { System.out.println(Before method: method.getName()); Object result method.invoke(target, args); System.out.println(After method: method.getName()); return result; }); } }优势代码更简洁性能优于传统反射调用7.3 字节码增强框架对比除了CGLIB现代Java生态中还有其他字节码操作框架框架特点适用场景Byte BuddyAPI友好性能优异支持Java新特性通用代理需求复杂字节码操作Javassist使用简单支持源码级操作快速开发简单类生成ASM底层控制极致性能框架开发性能敏感场景CGLIB成熟稳定Spring集成Spring生态传统项目Byte Buddy示例Class? dynamicType new ByteBuddy() .subclass(Object.class) .method(ElementMatchers.named(toString)) .intercept(FixedValue.value(Hello World!)) .make() .load(getClass().getClassLoader()) .getLoaded();7.4 代理模式与GraalVM原生镜像在GraalVM原生镜像中使用代理模式需要注意反射配置需要为所有通过反射访问的类和方法配置反射元数据代理类需要在native-image配置中明确声明动态代理限制需要提前注册所有可能的代理接口在native-image构建时添加配置{ name: com.example.UserService, proxy: true }替代方案考虑使用编译时代理生成如Micronauts的AOP实现对于简单场景可以使用手动实现的代理模式8. 设计模式组合应用实战在实际项目中代理模式很少单独使用通常会与其他设计模式组合应用。下面介绍几种典型的组合应用场景。8.1 代理模式工厂模式灵活代理创建通过工厂模式统一管理代理对象的创建public class ProxyFactory { private MapClass?, Object proxyCache new ConcurrentHashMap(); SuppressWarnings(unchecked) public T T getProxy(ClassT interfaceType, T target) { return (T) proxyCache.computeIfAbsent(interfaceType, k - Proxy.newProxyInstance( interfaceType.getClassLoader(), new Class?[]{interfaceType}, new LoggingInvocationHandler(target)) ); } private static class LoggingInvocationHandler implements InvocationHandler { private final Object target; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(调用方法: method.getName()); return method.invoke(target, args); } } }优势统一管理代理创建逻辑支持代理对象缓存便于扩展和修改代理行为8.2 代理模式策略模式动态代理行为根据不同的条件使用不同的代理策略public class DynamicInvocationHandler implements InvocationHandler { private final Object target; private final MapMethod, InvocationStrategy strategies; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { InvocationStrategy strategy strategies.getOrDefault(method, DefaultStrategy.INSTANCE); return strategy.invoke(target, method, args); } interface InvocationStrategy { Object invoke(Object target, Method method, Object[] args) throws Throwable; } enum DefaultStrategy implements InvocationStrategy { INSTANCE; public Object invoke(Object target, Method method, Object[] args) throws Throwable { return method.invoke(target, args); } } }8.3 代理模式组合模式复杂代理结构处理复杂的对象层级结构public class CompositeProxy implements InvocationHandler { private final MapClass?, Object targets; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { for (Object target : targets.values()) { if (method.getDeclaringClass().isInstance(target)) { return method.invoke(target, args); } } throw new UnsupportedOperationException(没有找到合适的实现); } }8.4 代理模式模板方法模式统一代理流程定义代理的标准流程public abstract class TemplateInvocationHandler implements InvocationHandler { protected abstract void preHandle(Method method, Object[] args); protected abstract Object doInvoke(Method method, Object[] args) throws Throwable; protected abstract void postHandle(Method method, Object[] args, Object result); public final Object invoke(Object proxy, Method method, Object[] args) throws Throwable { preHandle(method, args); Object result doInvoke(method, args); postHandle(method, args, result); return result; } }9. 代理模式在微服务架构中的创新应用在现代微服务架构中代理模式有了更多创新性的应用场景。9.1 服务网格(Service Mesh)中的Sidecar代理服务网格如Istio的核心架构就是基于代理模式架构原理每个服务实例配套部署一个Sidecar代理(如Envoy)所有进出流量都经过Sidecar代理代理实现服务发现、负载均衡、熔断等功能代理实现public class SidecarProxy implements InvocationHandler { private final ServiceDiscovery discovery; private final LoadBalancer loadBalancer; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 服务发现 ListInstanceInfo instances discovery.getInstances(method.getDeclaringClass().getName()); // 负载均衡 InstanceInfo selected loadBalancer.select(instances); // 远程调用 return remoteCall(selected, method, args); } }9.2 API网关中的动态路由代理API网关如Spring Cloud Gateway使用代理模式实现动态路由public class RoutingProxy implements InvocationHandler { private final RouteLocator routeLocator; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Route route routeLocator.getRoute(method.getName()); return dispatchRequest(route, method, args); } }9.3 分布式追踪中的上下文代理实现跨服务的上下文传递public class TracingProxy implements InvocationHandler { private final Object target; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Span span Tracer.startSpan(method.getName()); try { return method.invoke(target, args); } finally { span.finish(); } } }9.4 熔断降级代理实现服务的熔断降级功能public class CircuitBreakerProxy implements InvocationHandler { private final Object target; private final CircuitBreaker breaker; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (!breaker.allowRequest()) { return fallback(method, args); } try { Object result method.invoke(target, args); breaker.recordSuccess(); return result; } catch (Exception e) { breaker.recordFailure(); throw e; } } }10. 代理模式单元测试与集成测试为代理代码编写有效的测试是保证质量的关键。下面介绍代理模式相关的测试策略和技巧。10.1 代理对象单元测试测试策略测试代理逻辑是否正确执行验证前置/后置处理是否生效检查异常处理是否合理Mock测试示例public class LoggingProxyTest { Test public void testLoggingProxy() { // 创建mock目标对象 UserService mockService mock(UserService.class); when(mockService.addUser(test)).thenReturn(true); // 创建代理 UserService proxy ProxyFactory.createLoggingProxy(mockService); // 调用代理方法 boolean result proxy.addUser(test); // 验证 assertTrue(result); verify(mockService).addUser(test); // 可以添加日志输出的验证 } }10.2 AOP代理集成测试Spring测试配置SpringBootTest EnableAspectJAutoProxy public class AopIntegrationTest { Autowired private UserService userService; // 代理对象 Test public void testTransactionalProxy() { assertTrue(AopUtils.isAopProxy(userService)); assertTrue(AopUtils.isCglibProxy(userService)); userService.addUser(test); // 验证事务行为... } }10.3 代理性能测试使用JMH进行代理性能对比测试State(Scope.Thread) BenchmarkMode(Mode.Throughput) OutputTimeUnit(TimeUnit.SECONDS) public class ProxyPerformanceBenchmark { private UserService directInstance; private UserService jdkProxy; private UserService cglibProxy; Setup public void setup() { directInstance new UserServiceImpl(); jdkProxy createJdkProxy(directInstance); cglibProxy createCglibProxy(directInstance); } Benchmark public void baseline() { directInstance.addUser(test); } Benchmark public void testJdkProxy() { jdkProxy.addUser(test); } Benchmark public void testCglibProxy

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价