# springboot3demo **Repository Path**: l_o_a_n/springboot3demo ## Basic Information - **Project Name**: springboot3demo - **Description**: jdk17 + springboot3 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-13 - **Last Updated**: 2025-07-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 基于RabbitMQ的实例间方法同步解决方案 ## 概述 本项目实现了一个基于RabbitMQ的实例间方法同步机制。在分布式部署环境中,当一个服务实例执行某个特定方法时,其他服务实例也能自动执行相同的方法调用,从而实现多实例间的同步。 ## 核心组件 ### 1. @MethodSync 注解 用于标记需要同步的方法。 ```java @MethodSync(group = "test") public void syncMethod(String message) { // 方法实现 } ``` ### 2. MethodSyncAspect 切面 拦截标记了@MethodSync注解的方法,提取方法调用信息并发送到RabbitMQ。 该切面使用@Around通知,在方法执行完成后构造MethodInvocationDto对象,并通过MessageProducer发送到指定的交换机。主要处理流程包括: - 拦截标记了@MethodSync注解的方法调用 - 执行原方法并获取返回值 - 提取方法信息(类名、方法名、参数类型、参数值等) - 构造MethodInvocationDto对象 - 通过MessageProducer发送到RabbitMQ ### 3. MethodInvocationDto 传输对象 封装方法调用的相关信息,包括类名、方法名、参数类型和参数值等。 该类实现了Serializable接口,确保对象可以在网络间正确传输。主要包含以下字段: - className: 方法所在类的全限定名 - methodName: 方法名 - parameterTypes: 参数类型数组,用于反射调用时确定方法签名 - parameterValues: 参数值数组,包含实际传入的参数值 - timestamp: 调用时间戳,用于日志记录和调试 - group: 同步组名,用于区分不同的同步队列 ### 4. MessageProducer 消息生产者 负责将方法调用信息发送到RabbitMQ。 该类提供了多种消息发送方法,其中sendObjectMessage(String exchange, String routingKey, Object object)方法专门用于发送对象消息到指定交换机。在方法同步功能中,MethodSyncAspect通过此方法将MethodInvocationDto对象发送到method.sync.exchange交换机。 ### 5. MethodInvocationHandler 消息处理器 接收RabbitMQ中的方法调用消息,并通过反射执行相应的方法。 ## 工作原理 1. 当标记了@MethodSync注解的方法被调用时,MethodSyncAspect切面会拦截该方法调用。 2. 切面提取方法的类名、方法名、参数类型和参数值等信息,封装成MethodInvocationDto对象。 3. MethodInvocationDto对象通过MessageProducer发送到RabbitMQ的指定交换机和队列。 4. 其他服务实例中的MethodInvocationHandler监听该队列,接收到消息后进行反序列化。 5. MethodInvocationHandler通过反射机制创建类实例并调用对应的方法,实现参数的正确传递。 ### 消费者端处理流程 1. MethodInvocationHandler通过@RabbitListener注解监听METHOD_SYNC_QUEUE队列。 2. 当接收到MethodInvocationDto消息时,首先记录日志信息。 3. 调用invokeMethod方法进行反射执行: - 通过Class.forName获取方法所在类的Class对象 - 解析参数类型数组,处理基本数据类型和引用类型的转换 - 通过clazz.getMethod获取Method对象 - 通过Spring容器的ApplicationContext.getBean(clazz)获取类的bean实例 - 使用Spring的ConversionService对参数值进行类型转换,确保与方法签名匹配 - 调用method.invoke执行方法,传入转换后的参数值 ConversionService是Spring框架提供的类型转换服务,能够处理各种复杂的数据类型转换场景,包括但不限于: - 基本数据类型及其包装类之间的转换 - 字符串到枚举类型的转换 - 字符串到日期类型的转换 - JSON字符串到复杂对象的转换 - 集合类型之间的转换 通过使用ConversionService,我们避免了手动实现各种类型转换逻辑,提高了代码的可维护性和扩展性。 ## 配置说明 ### RabbitMQ配置 在`RabbitMQConfig`类中配置了方法同步所需的交换机、队列和绑定关系: - 交换机名称:`method.sync.exchange` - 队列名称:`method.sync.queue` - 路由键:`method.sync.routing.key` 配置类还设置了Jackson2JsonMessageConverter作为消息转换器,确保MethodInvocationDto对象能够正确地序列化为JSON格式进行传输,并在接收端自动反序列化为Java对象。 ### 同步组 @MethodSync注解支持group参数,用于区分不同的同步队列,实现更细粒度的同步控制。 ## 使用方法 1. 在需要同步的方法上添加@MethodSync注解: ```java @Service public class MethodSyncTestService { @MethodSync(group = "test") public void syncMethod(String message) { // 方法实现 } } ``` 2. 调用该方法时,其他服务实例也会执行相同的方法调用。 ## 测试接口 项目提供了统一的RabbitMQ测试接口: ### 基本消息发送测试 - `GET /rabbitmq/send-text?message=测试消息` - `GET /rabbitmq/send-object?content=对象消息内容` ### 方法同步测试 - `GET /rabbitmq/sync-method?message=测试消息` - `GET /rabbitmq/sync-method-with-params?id=1&name=test&count=10` - `GET /rabbitmq/sync-method-with-object?name=test&age=25&active=true` ## 依赖组件 - Spring Boot AOP - Spring Boot AMQP - Lombok ## 注意事项 1. 被同步的方法所在的类需要有无参构造函数。 2. 方法参数需要实现序列化接口。 3. 同步方法应该设计为幂等的,避免重复执行导致的问题。 4. 在生产环境中,需要考虑异常处理和消息确认机制。 5. 为了避免实例间方法同步导致的循环调用问题,项目使用了ThreadLocal标记机制。当方法通过MQ调用执行时,会通过MqProcessingMarker工具类设置一个线程局部变量标记,切面逻辑会检查这个标记,如果发现当前线程正在处理MQ消息,则会跳过切面逻辑,避免循环调用。 ## 扩展性 1. 可以通过group参数实现不同业务模块的独立同步。 2. 可以增加消息确认机制,确保消息被正确处理。 3. 可以增加同步日志记录,便于追踪和调试。