JAVA 动态代理:从原理剖析到实战应用

JAVA 动态代理:从原理剖析到实战应用

JAVA 动态代理:从原理剖析到实战应用

在这里插入图片描述

1.1 本章学习目标与重点

💡 掌握动态代理的核心概念与分类,理解动态代理在 Java 开发中的核心价值。
💡 熟练掌握 JDK 动态代理的实现流程与核心 API,能够独立编写 JDK 动态代理代码。
💡 了解 CGLIB 动态代理的实现原理与适用场景,对比 JDK 动态代理与 CGLIB 动态代理的差异。
💡 结合实际业务场景,掌握动态代理在 AOP 编程、权限控制、日志记录等场景中的实战应用。
⚠️ 本章重点是 JDK 动态代理的核心实现动态代理在 AOP 中的实战应用,这是 Java 高级开发与框架设计的必备技能。

1.2 动态代理的核心概念与价值

1.2.1 什么是动态代理

💡 动态代理 是 Java 设计模式中代理模式的一种高级实现,它允许程序在 运行时 动态生成目标类的代理对象,而无需在编译期手动编写代理类的代码。

在传统的静态代理模式中,我们需要为每个目标类手动编写对应的代理类,代理类与目标类实现相同的接口,这种方式存在代码冗余、扩展性差的问题。而动态代理则通过反射机制,在运行时动态创建代理类,实现了代理逻辑的复用,大幅提升了代码的灵活性和扩展性。

动态代理的核心思想是 “代理对象包裹目标对象,增强目标对象的方法功能”,代理对象可以在目标方法执行前后添加额外的逻辑,如日志记录、权限校验、事务管理等,而不需要修改目标对象的代码。

1.2.2 动态代理的核心价值

动态代理是 Java 高级开发中不可或缺的技术,其核心价值主要体现在以下几个方面:

  1. 解耦核心业务与非核心业务:将日志、事务、权限等通用功能从核心业务代码中抽离,实现 关注点分离
  2. 提升代码复用性:代理逻辑可以复用在多个目标类上,避免重复编写相同的增强代码。
  3. 增强代码扩展性:新增增强功能时,只需修改代理逻辑,无需修改目标类代码,符合 开闭原则
  4. 框架开发的核心基石:是 Spring AOP、MyBatis 等主流框架的底层实现技术,支撑了框架的核心功能。

1.2.3 动态代理的分类

根据实现方式的不同,Java 中的动态代理主要分为两类:

动态代理类型底层实现核心要求典型应用
JDK 动态代理Java 反射机制目标类必须实现一个或多个接口Spring AOP(默认)、自定义框架
CGLIB 动态代理字节码增强技术(ASM 框架)目标类可以不实现接口,不能是 final 类Spring AOP(目标类无接口时)、Hibernate

✅ 核心结论:动态代理的本质是 运行时生成代理类,增强目标方法功能,它是实现 AOP 编程的核心技术。

1.3 代理模式基础:静态代理

在学习动态代理之前,我们需要先掌握静态代理的实现方式,理解代理模式的核心思想,为动态代理的学习打下基础。

1.3.1 静态代理的核心角色

静态代理模式包含三个核心角色:

  1. 抽象角色:通常是一个接口,定义了目标对象和代理对象的共同方法。
  2. 目标角色:实现抽象角色的类,是代理对象所代理的真实对象,包含核心业务逻辑。
  3. 代理角色:实现抽象角色的类,包含对目标对象的引用,在目标方法执行前后添加增强逻辑。

1.3.2 静态代理的代码实现

/** * 静态代理示例:用户服务接口(抽象角色) */publicinterfaceUserService{voidaddUser(String username);voiddeleteUser(String userId);}/** * 目标角色:用户服务实现类 */publicclassUserServiceImplimplementsUserService{@OverridepublicvoidaddUser(String username){System.out.println("核心业务:添加用户 "+ username);}@OverridepublicvoiddeleteUser(String userId){System.out.println("核心业务:删除用户 "+ userId);}}/** * 代理角色:用户服务代理类 */publicclassUserServiceProxyimplementsUserService{// 维护目标对象的引用privatefinalUserService target;publicUserServiceProxy(UserService target){this.target = target;}@OverridepublicvoidaddUser(String username){// 前置增强:日志记录System.out.println("[日志] 执行 addUser 方法,参数:"+ username);// 执行目标方法 target.addUser(username);// 后置增强:事务提交System.out.println("[事务] 添加用户成功,事务提交");}@OverridepublicvoiddeleteUser(String userId){// 前置增强:日志记录System.out.println("[日志] 执行 deleteUser 方法,参数:"+ userId);// 执行目标方法 target.deleteUser(userId);// 后置增强:事务提交System.out.println("[事务] 删除用户成功,事务提交");}}/** * 测试类 */publicclassStaticProxyTest{publicstaticvoidmain(String[] args){// 创建目标对象UserService target =newUserServiceImpl();// 创建代理对象UserService proxy =newUserServiceProxy(target);// 通过代理对象调用方法 proxy.addUser("张三");System.out.println("---------------------------"); proxy.deleteUser("1001");}}

1.3.3 静态代理的优缺点

优点

  • 实现简单,易于理解和上手。
  • 不修改目标类代码,实现了核心业务与增强逻辑的分离。

缺点

  • 代码冗余:每个目标类都需要编写对应的代理类,当目标类较多时,代理类数量会急剧增加。
  • 扩展性差:新增增强功能时,需要修改所有代理类的代码。
  • 耦合度高:代理类与目标类实现相同的接口,接口变更时,代理类和目标类都需要修改。

⚠️ 注意事项:静态代理的缺点正是动态代理需要解决的问题,动态代理通过运行时生成代理类,完美解决了静态代理的代码冗余和扩展性问题。

1.4 JDK 动态代理核心实现

JDK 动态代理是 Java 官方提供的动态代理实现,底层基于 反射机制java.lang.reflect 包下的核心 API 实现。

1.4.1 JDK 动态代理的核心 API

JDK 动态代理的核心 API 包含两个关键类/接口:

  1. InvocationHandler 接口:这是调用处理器接口,代理对象的所有方法调用都会转发到该接口的 invoke 方法,我们需要实现该接口来编写增强逻辑。
  2. Proxy:这是代理类的生成器,通过其静态方法 newProxyInstance 可以在运行时动态生成代理对象。
核心方法详解
  • InvocationHandler.invoke(Object proxy, Method method, Object[] args)
    • proxy:生成的代理对象本身
    • method:被调用的目标方法对象
    • args:目标方法的参数数组
    • 作用:编写增强逻辑,并通过反射调用目标方法
  • Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
    • loader:目标类的类加载器
    • interfaces:目标类实现的接口数组
    • h:调用处理器对象
    • 作用:生成并返回动态代理对象

1.4.2 JDK 动态代理的实现步骤

💡 JDK 动态代理的实现可以分为以下四个核心步骤:
① 定义业务接口和目标类
② 实现 InvocationHandler 接口,编写增强逻辑
③ 通过 Proxy.newProxyInstance 生成代理对象
④ 通过代理对象调用目标方法

1.4.3 JDK 动态代理的代码实现

importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;/** * 步骤1:定义业务接口和目标类(复用静态代理的 UserService 和 UserServiceImpl) */publicinterfaceUserService{voidaddUser(String username);voiddeleteUser(String userId);}publicclassUserServiceImplimplementsUserService{@OverridepublicvoidaddUser(String username){System.out.println("核心业务:添加用户 "+ username);}@OverridepublicvoiddeleteUser(String userId){System.out.println("核心业务:删除用户 "+ userId);}}/** * 步骤2:实现 InvocationHandler 接口,编写增强逻辑 */publicclassLogTransactionInvocationHandlerimplementsInvocationHandler{// 维护目标对象的引用privatefinalObject target;publicLogTransactionInvocationHandler(Object target){this.target = target;}@OverridepublicObjectinvoke(Object proxy,Method method,Object[] args)throwsThrowable{Object result =null;try{// 前置增强:日志记录System.out.println("[日志] 执行方法:"+ method.getName()+",参数:"+(args ==null?"无": args[0]));// 反射调用目标方法 result = method.invoke(target, args);// 后置增强:事务提交System.out.println("[事务] 方法执行成功,事务提交");}catch(Exception e){// 异常增强:事务回滚System.out.println("[事务] 方法执行异常,事务回滚,异常信息:"+ e.getMessage());throw e;}return result;}}/** * 步骤3和4:生成代理对象并测试 */publicclassJdkDynamicProxyTest{publicstaticvoidmain(String[] args){// 1. 创建目标对象UserService target =newUserServiceImpl();// 2. 创建调用处理器对象InvocationHandler handler =newLogTransactionInvocationHandler(target);// 3. 生成动态代理对象UserService proxy =(UserService)Proxy.newProxyInstance( target.getClass().getClassLoader(),// 目标类的类加载器 target.getClass().getInterfaces(),// 目标类实现的接口 handler // 调用处理器);// 4. 通过代理对象调用方法System.out.println("===== 正常调用 ====="); proxy.addUser("李四");System.out.println("---------------------------"); proxy.deleteUser("1002");System.out.println("\n===== 异常调用 =====");// 模拟方法执行异常try{ proxy.addUser(null);}catch(Exception e){// 捕获异常}}}

1.4.4 运行结果与分析

===== 正常调用 ===== [日志] 执行方法:addUser,参数:李四 核心业务:添加用户 李四 [事务] 方法执行成功,事务提交 --------------------------- [日志] 执行方法:deleteUser,参数:1002 核心业务:删除用户 1002 [事务] 方法执行成功,事务提交 ===== 异常调用 ===== [日志] 执行方法:addUser,参数:null 核心业务:添加用户 null [事务] 方法执行异常,事务回滚,异常信息:null 

✅ 核心结论:JDK 动态代理通过 InvocationHandler 统一处理所有目标方法的增强逻辑,实现了代理逻辑的复用,解决了静态代理的代码冗余问题。

1.4.5 JDK 动态代理的注意事项

⚠️ 1. 目标类必须实现接口:JDK 动态代理是基于接口实现的,如果目标类没有实现任何接口,Proxy.newProxyInstance 方法会抛出 IllegalArgumentException 异常。
⚠️ 2. 代理对象是接口的实现类:通过 JDK 动态代理生成的代理对象,是目标类所实现接口的子类,不能将代理对象强制转换为目标类类型。
⚠️ 3. 增强逻辑统一化:所有目标方法的增强逻辑都写在 invoke 方法中,如果需要对不同方法进行不同增强,可以通过 method.getName() 进行判断。

1.5 CGLIB 动态代理核心实现

CGLIB(Code Generation Library)是一个基于字节码增强技术的动态代理框架,它弥补了 JDK 动态代理的不足,支持对没有实现接口的类进行代理。

1.5.1 CGLIB 动态代理的核心原理

CGLIB 动态代理的底层基于 ASM 字节码操作框架,它的核心原理是:

  1. 在运行时动态生成目标类的 子类,并重写目标类的非 final 方法。
  2. 在子类中嵌入增强逻辑,实现对目标方法的增强。
  3. 通过创建子类的实例,作为目标类的代理对象。

1.5.2 CGLIB 动态代理的核心 API

CGLIB 动态代理的核心 API 包含两个关键类:

  1. MethodInterceptor 接口:方法拦截器接口,类似于 JDK 动态代理的 InvocationHandler,代理对象的方法调用会转发到该接口的 intercept 方法。
  2. Enhancer:增强器类,用于生成目标类的子类(代理对象)。

1.5.3 CGLIB 动态代理的实现步骤

💡 CGLIB 动态代理的实现步骤如下:
① 引入 CGLIB 依赖
② 定义目标类(可以不实现接口)
③ 实现 MethodInterceptor 接口,编写增强逻辑
④ 通过 Enhancer 生成代理对象
⑤ 通过代理对象调用目标方法

1.5.4 CGLIB 动态代理的代码实现

步骤1:引入 CGLIB 依赖(Maven)
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version></dependency>
步骤2:编写目标类(无接口)
/** * 目标类:订单服务类(无实现任何接口) */publicclassOrderService{publicvoidcreateOrder(String orderId){System.out.println("核心业务:创建订单 "+ orderId);}publicvoidcancelOrder(String orderId){System.out.println("核心业务:取消订单 "+ orderId);}}
步骤3:实现 MethodInterceptor 接口
importnet.sf.cglib.proxy.MethodInterceptor;importnet.sf.cglib.proxy.MethodProxy;importjava.lang.reflect.Method;/** * CGLIB 方法拦截器:编写增强逻辑 */publicclassLogMethodInterceptorimplementsMethodInterceptor{/** * @param obj 代理对象(目标类的子类实例) * @param method 目标方法对象 * @param args 目标方法参数 * @param proxy 方法代理对象,用于调用目标方法 */@OverridepublicObjectintercept(Object obj,Method method,Object[] args,MethodProxy proxy)throwsThrowable{Object result =null;try{// 前置增强:日志记录System.out.println("[CGLIB 日志] 执行方法:"+ method.getName()+",参数:"+(args ==null?"无": args[0]));// 调用目标方法(通过 MethodProxy 调用,性能更高) result = proxy.invokeSuper(obj, args);// 后置增强:事务提交System.out.println("[CGLIB 事务] 方法执行成功,事务提交");}catch(Exception e){// 异常增强:事务回滚System.out.println("[CGLIB 事务] 方法执行异常,事务回滚,异常信息:"+ e.getMessage());throw e;}return result;}}
步骤4:生成代理对象并测试
importnet.sf.cglib.proxy.Enhancer;/** * CGLIB 动态代理测试类 */publicclassCglibDynamicProxyTest{publicstaticvoidmain(String[] args){// 1. 创建增强器对象Enhancer enhancer =newEnhancer();// 2. 设置目标类的字节码(父类) enhancer.setSuperclass(OrderService.class);// 3. 设置方法拦截器 enhancer.setCallback(newLogMethodInterceptor());// 4. 生成代理对象(目标类的子类实例)OrderService proxy =(OrderService) enhancer.create();// 5. 通过代理对象调用方法System.out.println("===== 正常调用 ====="); proxy.createOrder("ORDER_20260129");System.out.println("---------------------------"); proxy.cancelOrder("ORDER_20260129");System.out.println("\n===== 异常调用 =====");try{ proxy.createOrder(null);}catch(Exception e){// 捕获异常}}}

1.5.5 运行结果与分析

===== 正常调用 ===== [CGLIB 日志] 执行方法:createOrder,参数:ORDER_20260129 核心业务:创建订单 ORDER_20260129 [CGLIB 事务] 方法执行成功,事务提交 --------------------------- [CGLIB 日志] 执行方法:cancelOrder,参数:ORDER_20260129 核心业务:取消订单 ORDER_20260129 [CGLIB 事务] 方法执行成功,事务提交 ===== 异常调用 ===== [CGLIB 日志] 执行方法:createOrder,参数:null 核心业务:创建订单 null [CGLIB 事务] 方法执行异常,事务回滚,异常信息:null 

1.5.6 CGLIB 动态代理的注意事项

⚠️ 1. 目标类不能是 final 类:CGLIB 通过生成子类实现代理,如果目标类是 final 类,无法生成子类,会抛出 IllegalArgumentException 异常。
⚠️ 2. 目标方法不能是 final 方法:final 方法不能被子类重写,因此无法被 CGLIB 增强。
⚠️ 3. 性能优于 JDK 动态代理:CGLIB 基于字节码操作,直接生成字节码,性能比基于反射的 JDK 动态代理更高。

1.6 JDK 动态代理 vs CGLIB 动态代理

为了帮助大家更好地选择合适的动态代理技术,我们对 JDK 动态代理和 CGLIB 动态代理进行全面对比:

对比维度JDK 动态代理CGLIB 动态代理
底层实现Java 反射机制ASM 字节码增强技术
目标类要求必须实现接口可以不实现接口,不能是 final 类
代理对象生成方式实现目标类的接口生成目标类的子类
性能较低(反射调用)较高(直接操作字节码)
核心 APIInvocationHandlerProxyMethodInterceptorEnhancer
适用场景目标类实现接口的情况目标类未实现接口的情况
Spring AOP 默认选择目标类有接口时目标类无接口时

✅ 核心结论:在实际开发中,优先使用 JDK 动态代理(符合面向接口编程思想),当目标类没有实现接口时,再使用 CGLIB 动态代理。

1.7 动态代理的实战应用场景

动态代理在 Java 开发中应用广泛,尤其是在框架开发和业务系统设计中,以下是几个典型的实战应用场景。

1.7.1 场景1:基于动态代理的 AOP 日志框架

💡 核心需求:实现一个轻量级的 AOP 日志框架,自动记录所有业务方法的调用日志,包括方法名、参数、执行时间等信息。

代码实现
importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;importjava.util.Arrays;/** * AOP 日志框架:JDK 动态代理实现 */// 日志注解:标记需要记录日志的方法public@interfaceLoggable{}// 通用日志调用处理器publicclassLogInvocationHandlerimplementsInvocationHandler{privatefinalObject target;publicLogInvocationHandler(Object target){this.target = target;}@OverridepublicObjectinvoke(Object proxy,Method method,Object[] args)throwsThrowable{// 判断方法是否标记了 @Loggable 注解if(method.isAnnotationPresent(Loggable.class)){long startTime =System.currentTimeMillis();String methodName = method.getName();String params =Arrays.toString(args);// 前置日志System.out.println("[AOP 日志] 方法 "+ methodName +" 开始执行,参数:"+ params);// 执行目标方法Object result = method.invoke(target, args);// 后置日志long endTime =System.currentTimeMillis();System.out.println("[AOP 日志] 方法 "+ methodName +" 执行完毕,耗时:"+(endTime - startTime)+"ms,返回值:"+ result);return result;}else{// 未标记注解的方法,直接执行return method.invoke(target, args);}}// 生成代理对象的工具方法@SuppressWarnings("unchecked")publicstatic<T>TcreateProxy(T target){return(T)Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(),newLogInvocationHandler(target));}}// 业务接口publicinterfaceProductService{@LoggableStringgetProductById(String productId);StringgetProductName(String productId);}// 业务实现类publicclassProductServiceImplimplementsProductService{@OverridepublicStringgetProductById(String productId){// 模拟业务逻辑耗时try{Thread.sleep(100);}catch(InterruptedException e){ e.printStackTrace();}return"产品ID:"+ productId +",名称:Java 编程思想";}@OverridepublicStringgetProductName(String productId){return"Java 编程思想";}}// 测试类publicclassAopLogTest{publicstaticvoidmain(String[] args){ProductService target =newProductServiceImpl();ProductService proxy =LogInvocationHandler.createProxy(target);// 标记 @Loggable 的方法,会记录日志 proxy.getProductById("P1001");// 未标记 @Loggable 的方法,不会记录日志System.out.println("---------------------------"); proxy.getProductName("P1001");}}
运行结果
[AOP 日志] 方法 getProductById 开始执行,参数:[P1001] [AOP 日志] 方法 getProductById 执行完毕,耗时:101ms,返回值:产品ID:P1001,名称:Java 编程思想 --------------------------- 

1.7.2 场景2:基于动态代理的权限校验框架

💡 核心需求:实现一个权限校验框架,在方法执行前自动校验用户的权限,无权限则抛出异常。

代码实现
importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;importjava.util.HashSet;importjava.util.Set;/** * 权限校验注解:标记方法所需的权限 */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceRequiresPermission{String[]value();}/** * 用户上下文:存储当前登录用户的权限 */publicclassUserContext{privatestaticfinalThreadLocal<Set<String>> userPermissions =newThreadLocal<>();publicstaticvoidsetUserPermissions(String... permissions){Set<String> permissionSet =newHashSet<>();for(String permission : permissions){ permissionSet.add(permission);} userPermissions.set(permissionSet);}publicstaticSet<String>getUserPermissions(){return userPermissions.get();}publicstaticvoidclear(){ userPermissions.remove();}}/** * 权限校验调用处理器 */publicclassPermissionInvocationHandlerimplementsInvocationHandler{privatefinalObject target;publicPermissionInvocationHandler(Object target){this.target = target;}@OverridepublicObjectinvoke(Object proxy,Method method,Object[] args)throwsThrowable{// 判断方法是否需要权限校验if(method.isAnnotationPresent(RequiresPermission.class)){RequiresPermission annotation = method.getAnnotation(RequiresPermission.class);String[] requiredPermissions = annotation.value();Set<String> userPermissions =UserContext.getUserPermissions();// 校验权限boolean hasPermission =false;for(String permission : requiredPermissions){if(userPermissions.contains(permission)){ hasPermission =true;break;}}if(!hasPermission){thrownewSecurityException("权限不足,所需权限:"+String.join(",", requiredPermissions));}}// 执行目标方法return method.invoke(target, args);}// 生成代理对象的工具方法@SuppressWarnings("unchecked")publicstatic<T>TcreateProxy(T target){return(T)Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(),newPermissionInvocationHandler(target));}}// 业务接口publicinterfaceAdminService{@RequiresPermission({"admin:user:add"})voidaddUser(String username);@RequiresPermission({"admin:user:delete"})voiddeleteUser(String userId);}// 业务实现类publicclassAdminServiceImplimplementsAdminService{@OverridepublicvoidaddUser(String username){System.out.println("添加用户成功:"+ username);}@OverridepublicvoiddeleteUser(String userId){System.out.println("删除用户成功:"+ userId);}}// 测试类publicclassPermissionTest{publicstaticvoidmain(String[] args){AdminService target =newAdminServiceImpl();AdminService proxy =PermissionInvocationHandler.createProxy(target);// 测试1:用户拥有 admin:user:add 权限System.out.println("===== 有权限调用 =====");UserContext.setUserPermissions("admin:user:add"); proxy.addUser("王五");// 测试2:用户没有 admin:user:delete 权限System.out.println("\n===== 无权限调用 =====");try{ proxy.deleteUser("1003");}catch(Exception e){System.out.println(e.getMessage());}UserContext.clear();}}
运行结果
===== 有权限调用 ===== 添加用户成功:王五 ===== 无权限调用 ===== 权限不足,所需权限:admin:user:delete 

1.7.3 场景3:Spring AOP 中的动态代理应用

💡 Spring AOP 是动态代理的典型应用,它底层同时支持 JDK 动态代理和 CGLIB 动态代理:

  1. 当目标类实现接口时,Spring AOP 默认使用 JDK 动态代理。
  2. 当目标类没有实现接口时,Spring AOP 自动切换为 CGLIB 动态代理。
  3. 开发者可以通过配置 proxy-target-class="true",强制 Spring AOP 使用 CGLIB 动态代理。

Spring AOP 通过动态代理,实现了横切关注点的统一管理,如日志、事务、权限等功能,大幅提升了代码的复用性和扩展性。

1.8 动态代理的优缺点与最佳实践

1.8.1 动态代理的优点

  1. 解耦核心业务与增强逻辑:将通用功能从核心业务中抽离,实现关注点分离。
  2. 代码复用性高:一套增强逻辑可以复用在多个目标类上,避免重复编码。
  3. 扩展性强:新增增强功能时,只需修改代理逻辑,无需修改目标类代码。
  4. 符合开闭原则:对扩展开放,对修改关闭,是优秀的设计模式实践。

1.8.2 动态代理的缺点

  1. 性能损耗:JDK 动态代理基于反射,存在一定的性能损耗;CGLIB 性能较高,但也比直接调用目标方法慢。
  2. 调试困难:代理对象是运行时生成的,调试时难以跟踪代码执行流程。
  3. 技术门槛高:动态代理涉及反射、字节码操作等高级技术,对开发者的技术水平要求较高。

1.8.3 动态代理的最佳实践

  1. 优先使用 JDK 动态代理:符合面向接口编程思想,代码更具规范性和可维护性。
  2. 合理选择增强时机:对于性能敏感的场景,尽量减少动态代理的使用,或选择 CGLIB 动态代理。
  3. 结合注解使用:通过注解标记需要增强的方法,实现增强逻辑的精准控制。
  4. 使用成熟框架:优先使用 Spring AOP 等成熟框架,避免重复造轮子,提升开发效率。
  5. 做好异常处理:在增强逻辑中处理目标方法的异常,避免异常扩散导致程序崩溃。

1.9 实战案例:基于动态代理的事务管理框架

1.9.1 需求分析

💡 实现一个轻量级的事务管理框架,要求:

  1. 通过注解标记需要事务管理的方法。
  2. 支持事务的自动提交和回滚。
  3. 事务管理逻辑与核心业务逻辑解耦。
  4. 支持 JDK 动态代理和 CGLIB 动态代理。

1.9.2 代码实现

importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;importnet.sf.cglib.proxy.Enhancer;importnet.sf.cglib.proxy.MethodInterceptor;importnet.sf.cglib.proxy.MethodProxy;/** * 事务注解:标记需要事务管理的方法 */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceTransactional{}/** * 事务管理器:模拟事务的提交和回滚 */publicclassTransactionManager{publicvoidbeginTransaction(){System.out.println("[事务] 开启事务");}publicvoidcommit(){System.out.println("[事务] 提交事务");}publicvoidrollback(){System.out.println("[事务] 回滚事务");}}/** * JDK 动态代理事务处理器 */publicclassJdkTransactionInvocationHandlerimplementsInvocationHandler{privatefinalObject target;privatefinalTransactionManager transactionManager =newTransactionManager();publicJdkTransactionInvocationHandler(Object target){this.target = target;}@OverridepublicObjectinvoke(Object proxy,Method method,Object[] args)throwsThrowable{Object result =null;// 判断方法是否需要事务管理if(method.isAnnotationPresent(Transactional.class)){ transactionManager.beginTransaction();try{ result = method.invoke(target, args); transactionManager.commit();}catch(Exception e){ transactionManager.rollback();throw e;}}else{ result = method.invoke(target, args);}return result;}@SuppressWarnings("unchecked")publicstatic<T>TcreateJdkProxy(T target){return(T)Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(),newJdkTransactionInvocationHandler(target));}}/** * CGLIB 动态代理事务拦截器 */publicclassCglibTransactionInterceptorimplementsMethodInterceptor{privatefinalObject target;privatefinalTransactionManager transactionManager =newTransactionManager();publicCglibTransactionInterceptor(Object target){this.target = target;}@OverridepublicObjectintercept(Object obj,Method method,Object[] args,MethodProxy proxy)throwsThrowable{Object result =null;if(method.isAnnotationPresent(Transactional.class)){ transactionManager.beginTransaction();try{ result = proxy.invokeSuper(obj, args); transactionManager.commit();}catch(Exception e){ transactionManager.rollback();throw e;}}else{ result = proxy.invokeSuper(obj, args);}return result;}@SuppressWarnings("unchecked")publicstatic<T>TcreateCglibProxy(T target){Enhancer enhancer =newEnhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(newCglibTransactionInterceptor(target));return(T) enhancer.create();}}/** * 业务接口 */publicinterfaceAccountService{@Transactionalvoidtransfer(String fromAccount,String toAccount,double amount);}/** * 业务实现类 */publicclassAccountServiceImplimplementsAccountService{@Overridepublicvoidtransfer(String fromAccount,String toAccount,double amount){System.out.println("核心业务:从账户 "+ fromAccount +" 转账 "+ amount +" 到账户 "+ toAccount);// 模拟转账异常if(amount <0){thrownewIllegalArgumentException("转账金额不能为负数");}}}/** * 测试类 */publicclassTransactionTest{publicstaticvoidmain(String[] args){// JDK 动态代理测试System.out.println("===== JDK 动态代理事务测试 =====");AccountService jdkProxy =JdkTransactionInvocationHandler.createJdkProxy(newAccountServiceImpl());// 正常转账 jdkProxy.transfer("A1001","A1002",1000.0);System.out.println("---------------------------");// 异常转账try{ jdkProxy.transfer("A1001","A1002",-500.0);}catch(Exception e){System.out.println("转账失败:"+ e.getMessage());}// CGLIB 动态代理测试(无接口类)System.out.println("\n===== CGLIB 动态代理事务测试 =====");OrderService cglibProxy =CglibTransactionInterceptor.createCglibProxy(newOrderService()); cglibProxy.createOrder("ORDER_20260129");}}

1.9.3 运行结果

===== JDK 动态代理事务测试 ===== [事务] 开启事务 核心业务:从账户 A1001 转账 1000.0 到账户 A1002 [事务] 提交事务 --------------------------- [事务] 开启事务 核心业务:从账户 A1001 转账 -500.0 到账户 A1002 [事务] 回滚事务 转账失败:转账金额不能为负数 ===== CGLIB 动态代理事务测试 ===== [CGLIB 日志] 执行方法:createOrder,参数:ORDER_20260129 核心业务:创建订单 ORDER_20260129 [CGLIB 事务] 方法执行成功,事务提交 

1.9.4 案例总结

✅ 这个事务管理框架综合运用了 JDK 动态代理CGLIB 动态代理 技术,核心亮点如下:

  1. 通过 @Transactional 注解标记需要事务管理的方法,配置简单。
  2. 事务管理逻辑与核心业务逻辑完全解耦,符合关注点分离原则。
  3. 支持两种动态代理方式,适配不同的目标类场景。
  4. 实现了事务的自动提交和回滚,保证了数据的一致性。

1.10 本章总结

  1. 动态代理是代理模式的高级实现,分为 JDK 动态代理CGLIB 动态代理 两类。
  2. JDK 动态代理基于反射机制,要求目标类实现接口;CGLIB 动态代理基于字节码增强,支持无接口类。
  3. 动态代理的核心是 运行时生成代理对象,增强目标方法功能,是实现 AOP 编程的核心技术。
  4. 动态代理广泛应用于日志记录、权限校验、事务管理等场景,是 Spring AOP 等框架的底层实现。
  5. 动态代理的最佳实践是“优先使用 JDK 动态代理,结合注解精准控制,使用成熟框架提升效率”。
  6. 动态代理的本质是解耦核心业务与增强逻辑,提升代码的复用性和扩展性,符合开闭原则。

Read more

Launch4j:轻量级 Java 应用 Windows 打包方案

Launch4j:轻量级 Java 应用 Windows 打包方案

Launch4j 是一款开源工具,专注于将 Java 程序(JAR 文件)封装为 Windows 原生可执行文件(.exe)。其核心原理是为 JAR 文件添加一个轻量级启动器,用户无需安装 Java 环境即可直接双击运行,体验与原生应用无异。 核心优势与特性 无缝用户体验 通过生成的 .exe 文件,用户无需手动配置 Java 环境或执行命令行操作。启动器自动检测系统 JRE 或使用捆绑的运行时,实现开箱即用。 原生集成能力 支持为可执行文件嵌入自定义图标、版本信息、公司名称等元数据。提供进程名称控制、单实例运行、UAC 权限管理等功能,使 Java 应用更贴近原生软件体验。 高效打包机制 采用内存映射技术直接加载内嵌 JAR,避免释放临时文件,既提升启动速度又降低代码泄露风险。支持 32/64 位架构,

By Ne0inhk
使用飞算JavaAI搞定学生管理系统

使用飞算JavaAI搞定学生管理系统

标签<#JavaAI 飞算 JavaAI 的开发流程颠覆了我对传统开发的认知,整个过程就像和一位经验丰富的架构师实时协作,一下是我对开发学生管理系统的一些理解余流程操作 项目初始化阶段:在打开飞算 JavaAI 后,我创建了名一个"JavaProject" 的新项目,AI自动生成了基础的项目结构,包括IDEA配置文件夹、src 源代码目录、SQL文件夹和核心的 pom.xml 文件。这一步省去了传统开发中手动配置 Maven、设置项目结构的繁琐过程。 这里我自己的实操SQL数据库导入不了 但是在返回代码生成部分,表格设计这一块会有一个自动表格设计,在这里能帮你连接到数据库,后续的JavaAI就能按照这个数据库进行快速创作。 需求定义阶段:在飞算 JavaAI 的智能引导模块,输入了详细的需求,要飞算avaAI开发一个学生成绩管理系统,包含学生信息管理、课程管理、成绩录入、成绩统计分析、数据导出等功能,采用 SpringBoot 框架,MySQL 数据库。让我惊讶的是,

By Ne0inhk
Flutter 三方库 js_wrapping 的鸿蒙化适配指南 - 实现 Dart 与 JavaScript 的无缝对象包装、支持强类型回调与属性映射

Flutter 三方库 js_wrapping 的鸿蒙化适配指南 - 实现 Dart 与 JavaScript 的无缝对象包装、支持强类型回调与属性映射

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 js_wrapping 的鸿蒙化适配指南 - 实现 Dart 与 JavaScript 的无缝对象包装、支持强类型回调与属性映射 前言 在进行 Flutter for OpenHarmony 的 Web 混合开发时,频繁地在 Dart 层与底层 JavaScript 环境进行数据交互是不可避免的。虽然官方提供了基本的 dart:js,但在处理复杂的 JS 对象和回调时,代码往往会变得杂乱无章。js_wrapping 提供了一个更优雅的、类型安全的包装层。本文将指导大家如何在鸿蒙端利用该库提升 JS 互操作的开发体验。 一、原理解析 / 概念介绍 1.1 基础原理

By Ne0inhk

我和 AI 聊了一晚上,第二天它说“你好,请问有什么可以帮你?“凌晨我的 AI 尽然悄悄把记忆清空了!——OpenClaw Session 完全生存指南:重置、压缩、剪枝、记忆一网打尽

凌晨4点,我的 AI 悄悄把记忆清空了——OpenClaw Session 避坑指南 摘要:用 OpenClaw 搭了个 AI 助手,聊得好的,第二天一早它就"失忆"了?本文从一个真实踩坑出发,系统拆解 OpenClaw 的 Session 机制——重置(Reset)、压缩(Compaction)、剪枝(Pruning)、记忆(Memory)、会话控制(Session Tool)——帮你彻底搞懂"对话为什么会消失"以及"怎么让 AI 记住你"。 🤯 踩坑现场 事情是这样的: 我用 OpenClaw

By Ne0inhk