核心内容摘要
智能菜谱推荐系统设计毕业设计源码(源码+lw+部署文档+讲解等)
一ã€�æ ¸å¿ƒå�Ÿç�†åŸºäº�观察者模å¼�的轻é‡�å®�ç�°Spring事件模å¼�本质是对观察者模å¼�å�‘布-订阅模å¼�çš„å°�装ä¸�å¢�å¼ºæ ¸å¿ƒç›®æ ‡æ˜¯å®�ç�°ç»„ä»¶é—´æ�¾è€¦å�ˆé€šä¿¡â€”—让事件å�‘布者ä¸�监å�¬è€…互ä¸�ç›´æ�¥ä¾�赖通过ä¸é—´äº‹ä»¶è½½ä½“完æˆ�交互。其è¿�行ä¾�èµ–å››å¤§æ ¸å¿ƒç»„ä»¶å��å�Œæ”¯æ’‘事件的å�‘布ã€�广æ’ä¸�处ç�†å…¨æµ�程。
1 å››å¤§æ ¸å¿ƒç»„ä»¶äº‹ä»¶Eventæ•°æ�®è½½ä½“å°�è£…éœ€ä¼ é€’çš„ä¸šåŠ¡ä¿¡æ�¯ã€‚Spring
2�需继承ApplicationEvent抽象类基�JDKEventObject
2å��支æŒ�ä»»æ„�POJO作为事件ç�µæ´»æ€§æ˜¾è‘—æ��å�‡ã€‚常è§�场景如用户注册ã€�订å�•状æ€�å�˜æ›´äº‹ä»¶ä»…需å°�è£…æ ¸å¿ƒå—æ®µç”¨æˆ·IDã€�订å�•å�·ç‰å�³å�¯ã€‚事件å�‘布者Publisher负责触å�‘å¹¶å�‘布事件通过ApplicationEventPublisheræ�¥å�£çš„publishEvent()方法å®�ç�°ã€‚å› Spring容器ApplicationContext本身å®�ç�°äº†è¯¥æ�¥å�£Beanå�¯ç›´æ�¥æ³¨å…¥ApplicationEventPublisher或通过ApplicationEventPublisherAwareæ�¥å�£è�·å�–å�‘布能力。事件监å�¬å™¨Listener订阅并处ç�†ç‰¹å®šäº‹ä»¶çš„ä¸šåŠ¡è½½ä½“æ ¸å¿ƒæ˜¯ç»‘å®šç›®æ ‡äº‹ä»¶ç±»å�‹å¹¶æ‰§è¡Œé€»è¾‘支æŒ�å�Œæ¥ã€�异æ¥ã€�æ�¡ä»¶è¿‡æ»¤ç‰å¢�强特性。事件广æ’器Multicasterè¿�æ�¥å�‘布者ä¸�监å�¬è€…çš„æ ¸å¿ƒæ�¢çº½é»˜è®¤å®�ç�°ä¸ºSimpleApplicationEventMulticaster。其è�Œè´£æ˜¯æ�¥æ”¶å�‘布者事件ã€�ç›é€‰åŒ¹é…�监å�¬å™¨å†�将事件分å�‘给对应监å�¬å™¨æ˜¯äº‹ä»¶æµ�转的关键ä¸è½¬ç«™ã€‚
2 完整è¿�行æµ�程事件触å�‘æ ¸å¿ƒä¸šåŠ¡é€»è¾‘æ‰§è¡Œå®Œæˆ�å��如用户注册æˆ�功å�‘布者调用publishEvent()æ–¹æ³•ä¼ å…¥äº‹ä»¶å¯¹è±¡äº‹ä»¶è½¬å�‘ApplicationEventPublisher将事件委托给ApplicationEventMulticaster监å�¬å™¨åŒ¹é…�广æ’å™¨æ ¹æ�®äº‹ä»¶ç±»å�‹ç›é€‰å‡ºæ‰€æœ‰è®¢é˜…该事件的监å�¬å™¨æ”¯æŒ�æ³›å�‹åŒ¹é…�ã€�æ�¡ä»¶è¿‡æ»¤äº‹ä»¶å¤„ç�†å¹¿æ’器将事件分å�‘给匹é…�监å�¬å™¨æ‰§è¡Œé»˜è®¤å�Œæ¥æ‰§è¡Œå�‘布者阻å¡�ç‰å¾…所有监å�¬å™¨å®Œæˆ�å�¯é…�置为异æ¥ã€‚二ã€�深度ç�†è§£æ ¸å¿ƒä»·å€¼ä¸�关键特性
1 æ ¸å¿ƒä»·å€¼è§£è€¦ä¸�æ‰©å±•ä¼ ç»Ÿä¸šåŠ¡ä¸ä¸»çº¿é€»è¾‘ä¸�副线逻辑常通过直æ�¥è°ƒç”¨è€¦å�ˆå¦‚用户注册å��ç›´æ�¥è°ƒç”¨çŸä¿¡ã€�ä¼˜æƒ åˆ¸æœ�务导致代ç �臃肿ã€�扩展性差。Spring事件模å¼�通过“事件契约â€�拆分逻辑å�‘布者仅负责å�‘布事件ä¸�关心è°�处ç�†ç›‘å�¬è€…仅关注事件处ç�†ä¸�关心事件æ�¥æº�æ ¸å¿ƒä»·å€¼ä½“ç�°åœ¨é™�ä½�耦å�ˆæ¨¡å�—é—´ä»…ä¾�èµ–äº‹ä»¶å¯¹è±¡æ— ç›´æ�¥å¼•用修改æŸ�一逻辑如新å¢�æ�¨é€�æœ�åŠ¡æ— éœ€æ”¹åŠ¨ä¸»çº¿ä»£ç �å¢�强å�¯æ‰©å±•æ–°å¢�å‰¯çº¿ä¸šåŠ¡ä»…éœ€æ·»åŠ ç›‘å�¬å™¨ç¬¦å�ˆâ€œå¼€é—å�Ÿåˆ™â€�å¼‚æ¥æ��速日志ã€�通知ç‰é��æ ¸å¿ƒé€»è¾‘å¼‚æ¥å¤„ç�†é�¿å…�阻å¡�主线æµ�程æ��å�‡æ�¥å�£å“�应速度è�Œè´£å�•一主线è�šç„¦æ ¸å¿ƒä¸šåŠ¡å¦‚æ³¨å†Œå‰¯çº¿é€»è¾‘åˆ†æ•£åˆ°å¯¹åº”ç›‘å�¬å™¨ä»£ç �å�¯è¯»æ€§ä¸�å�¯ç»´æŠ¤æ€§æ›´å¼ºã€‚
2 关键特性解�
2.
1 å�Œæ¥ä¸�å¼‚æ¥æ‰§è¡Œé»˜è®¤å�Œæ¥æ‰§è¡Œå�‘布者线程会ç‰å¾…所有监å�¬å™¨å¤„ç�†å®Œæˆ�适用äº�需ä¿�è¯�æ•°æ�®ä¸€è‡´æ€§çš„场景如订å�•创建å��å�Œæ¥æ‰£å‡�库å˜ã€‚异æ¥é…�置需两æ¥é…�ç½®ç±»æ·»åŠ EnableAsync注解开å�¯å¼‚æ¥æ”¯æŒ�监å�¬å™¨æ–¹æ³•æ·»åŠ Asyncæ³¨è§£æŒ‡å®šå¼‚æ¥æ‰§è¡Œã€‚å»ºè®®è‡ªå®šä¹‰çº¿ç¨‹æ± æ›¿ä»£é»˜è®¤SimpleAsyncTaskExecutor默认æ¯�次创建新线程性能较差。
2.
2 事务绑定事件部分场景需确�事务�交��执行事件如订�支付�功��券��事务�滚导致数��一致�通过TransactionalEventListener替代EventListener支�指定事务阶段触�phase TransactionPhase.AFTER_COMMIT默认事务�交�触�phase TransactionPhase.AFTER_ROLLBACK事务�滚�触�phase TransactionPhase.BEFORE_COMMIT事务�交�触�。
2.
3 监å�¬å™¨æ‰§è¡Œé¡ºåº�多个监å�¬å™¨è®¢é˜…å�Œä¸€äº‹ä»¶æ—¶å�¯é€šè¿‡Order注解数值越å°�优先级越高或Orderedæ�¥å�£æŒ‡å®šé¡ºåº�。注æ„�异æ¥åœºæ™¯ä¸‹Orderå¤±æ•ˆå› ç›‘å�¬å™¨åœ¨ä¸�å�Œçº¿ç¨‹æ‰§è¡Œæ— 法ä¿�è¯�顺åº�。
2.
4 ä¸�消æ�¯é˜Ÿåˆ—MQ的区别Spring事件是JVM内部轻é‡�通信方å¼�ä¸�MQ定ä½�差异æ˜�显需按需选择特性Spring事件MQKafka/RabbitMQ作用范围å�•体应用内å�Œä¸€JVM跨进程ã€�è·¨æœ�务分布å¼�æŒ�ä¹…åŒ–æ— è¿›ç¨‹å´©æºƒäº‹ä»¶ä¸¢å¤±æ”¯æŒ�æŒ�久化å�¯é� 性高适用场景å�•体/å�•æœ�务内解耦ã€�è½»é‡�业务微æœ�务跨æœ�务通信ã€�高å�¯é� 需求三ã€�å®�战案例用户注册场景完整å�¯è¿�行版本案例基äº�Spring Boot
2.
xå®�ç�°â€œç”¨æˆ·æ³¨å†Œæˆ�功å��â€�多场景è�”动å�Œæ¥å�‘欢è¿�邮件ã€�异æ¥å�‘æ–°äººä¼˜æƒ åˆ¸ã€�事务æ��交å��记录日志补充ä¾�èµ–ã€�异常处ç�†ä¸�测试æ¥éª¤ç¡®ä¿�代ç �å�¯ç›´æ�¥å¤�用。
1 �境准备
3.
1 ä¾�赖引入Mavenlt;dependenciesgt; !-- Spring Bootæ ¸å¿ƒä¾�èµ– -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-contextlt;/artifactIdgt; lt;/dependencygt; !-- Webä¾�赖用äº�æ�¥å�£æµ‹è¯• -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-weblt;/artifactIdgt; lt;/dependencygt; !-- JPAä¾�赖模拟数æ�®åº“事务 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpalt;/artifactIdgt; lt;/dependencygt; !-- H2å†…å˜æ•°æ�®åº“æ— éœ€é¢�外部署 -- dependency groupIdcom.h2database/groupId artifactIdh2/artifactId scoperuntime/scope /dependency /dependencies
3.
2 �置文件application.ymlspring: # H2数�库�置 datasource: url: jdbc:h2:mem:testdb driver-class-name: org.h
Driver username: sa password: # JPAé…�置自动建表ã€�打å�°SQL jpa: hibernate: ddl-auto: create-drop # å�¯åŠ¨å»ºè¡¨å…³é—åˆ è¡¨ä»…æµ‹è¯•ç”¨ show-sql: true properties: hibernate: format_sql: true # H2æ�§åˆ¶å�°è®¿é—®http://localhost:8080/h2-console h2: console: enabled: true # 自定义异æ¥çº¿ç¨‹æ± é…�ç½® async: executor: core-pool-size: 5 max-pool-size: 10 queue-capacity: 20 thread-name-prefix: EventAsync-
3.
3 æ ¸å¿ƒé…�置类import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.transaction.annotation.EnableTransactionManagement; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; Configuration EnableAsync // å¼€å�¯å¼‚æ¥æ”¯æŒ� EnableTransactionManagement // å¼€å�¯äº‹åŠ¡ç®¡ç�† EnableScheduling public class EventConfig { Value(${async.executor.core-pool-size}) private int corePoolSize; Value(${async.executor.max-pool-size}) private int maxPoolSize; Value(${async.executor.queue-capacity}) private int queueCapacity; Value(${async.executor.thread-name-prefix}) private String threadNamePrefix; // 自定义异æ¥çº¿ç¨‹æ± Bean(name eventTaskExecutor) public Executor eventTaskExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setThreadNamePrefix(threadNamePrefix); // æ‹’ç»�ç–ç•¥çº¿ç¨‹æ± æ»¡æ—¶ç”±è°ƒç”¨çº¿ç¨‹æ‰§è¡Œé�¿å…�任务丢失 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } // 异æ¥å¼‚常统一处ç�†å™¨ Bean public AsyncUncaughtExceptionHandler asyncUncaughtExceptionHandler() { return (ex, method, params) - { System.err.println(异æ¥ä»»åŠ¡æ‰§è¡Œå¼‚å¸¸æ–¹æ³• method.getName() 异常信æ�¯ ex.getMessage()); ex.printStackTrace(); }; } }
2 æ ¸å¿ƒå®�体ä¸�事件定义
3.
1 Userå®�ä½“ç±»æ˜ å°„æ•°æ�®åº“表import lombok.Data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import java.io.Serializable; Entity // JPAå®�体注解对应数æ�®åº“表 Data // Lombok自动生æˆ�getterã€�setterã€�toString public class User implements Serializable { private static final long serialVersionUID 1L; Id // 主键 GeneratedValue(strategy GenerationType.IDENTITY) // 自å¢�ç–ç•¥ private Long userId; private String username; private String email; private String password; // å®�é™…å¼€å�‘éœ€åŠ å¯†å˜å‚¨ }
3.
2 自定义事件UserRegisteredEvent用POJOå°�装事件数æ�®å—段设为finalä¿�è¯�ä¸�å�¯å�˜é�¿å…�监å�¬è¿‡ç¨‹ä¸æ•°æ�®è¢«ç¯¡æ”¹// 用户注册事件Spring
2æ— éœ€ç»§æ‰¿ApplicationEvent public class UserRegisteredEvent { // äº‹ä»¶æ ¸å¿ƒæ•°æ�®ä¸�å�¯å�˜ private final Long userId; private final String username; private final String email; // å…¨å�‚æ�„é€ å™¨åˆ�始化事件数æ�® public UserRegisteredEvent(Long userId, String username, String email) { this.userId userId; this.username username; this.email email; } // ä»…æ��ä¾›getteræ— setter public Long getUserId() { return userId; } public String getUsername() { return username; } public String getEmail() { return email; } }
3 事件å�‘布者å®�ç�°æ ¸å¿ƒä¸šåŠ¡æœ�务UserServiceå®�ç�°æ³¨å†Œæ ¸å¿ƒé€»è¾‘注入JPA Repositoryæ“�作数æ�®åº“事务æ��交å��å�‘布事件å�Œæ—¶å¤„ç�†ä¸šåС异叏import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; Service public class UserService { Autowired private UserRepository userRepository; // JPAæ•°æ�®è®¿é—®æ�¥å�£ Autowired private ApplicationEventPublisher eventPublisher; // 事件å�‘布器 // 事务注解ä¿�è¯�注册逻辑ä¸�æ•°æ�®åº“æ“�作å�Ÿå�性 Transactional(rollbackFor Exception.class) public void register(User user) { try { //
æ ¸å¿ƒä¸šåŠ¡åŠ å¯†å¯†ç �模拟å®�际用BCryptç‰åР坆 user.setPassword(encrypted_ user.getPassword()); //
ä¿�å˜ç”¨æˆ·åˆ°æ•°æ�®åº“ User savedUser userRepository.save(user); System.out.println(用户[ savedUser.getUsername() ]注册æˆ�功ID savedUser.getUserId()); //
å�‘布用户注册事件事务æ��交å��事务绑定监å�¬å™¨æ‰�会执行 eventPublisher.publishEvent(new UserRegisteredEvent( savedUser.getUserId(), savedUser.getUsername(), savedUser.getEmail() )); } catch (Exception e) { System.err.println(用户注册失败å�Ÿå› e.getMessage()); throw e; // 抛出异常触å�‘事务å›�滚 } } }
3.
1 UserRepositoryJPAæ•°æ�®è®¿é—®æ�¥å�£import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; // JpaRepositoryæ��ä¾›CRUDã€�分页ç‰åŸºç¡€æ–¹æ³•æ— éœ€æ‰‹åŠ¨å®�ç�° Repository public interface UserRepository extends JpaRepositoryUser, Long { // 自定义查询判æ–用户å��是å�¦å·²å˜åœ¨ boolean existsByUsername(String username); }
4 事件监å�¬å™¨å®�ç�°å¤šåœºæ™¯è�”动定义3个监å�¬å™¨è¦†ç›–å�Œæ¥ã€�异æ¥ã€�事务绑定场景å�Œæ—¶æ·»åР异叏æ�•è�·import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.transaction.event.TransactionPhase; import org.springframework.transaction.event.TransactionalEventListener; import org.springframework.core.annotation.Order; Component // 交给Spring管ç�† public class UserRegisteredListeners { //
å�Œæ¥ç›‘å�¬å�‘é€�欢è¿�邮件需å�Šæ—¶å��馈优先级最高 EventListener Order(
// 数值越�优先级越高 public void sendWelcomeEmail(UserRegisteredEvent event) { try { // 模拟邮件��耗时�作�际调用邮件SDK Thread.sleep(
; System.out.println(ã€�å�Œæ¥ä»»åŠ¡ã€‘å�‘é€�欢è¿�邮件给用户[ event.getUsername() ]邮箱 event.getEmail()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println(å�‘é€�欢è¿�邮件失败用户ID event.getUserId()); } } //
异æ¥ç›‘å�¬å�‘æ”¾æ–°äººä¼˜æƒ åˆ¸é��æ ¸å¿ƒé€»è¾‘ç»‘å®šè‡ªå®šä¹‰çº¿ç¨‹æ± Async(eventTaskExecutor) EventListener Order(
public void grantNewUserCoupon(UserRegisteredEvent event) { // æ¨¡æ‹Ÿä¼˜æƒ åˆ¸å�‘æ”¾é€»è¾‘è°ƒç”¨ä¼˜æƒ åˆ¸æœ�务 System.out.println(ã€�异æ¥ä»»åŠ¡ã€‘å�‘æ”¾æ–°äººä¼˜æƒ åˆ¸ç»™ç”¨æˆ·[ event.getUserId() ]线程å�� Thread.currentThread().getName()); } //
事务绑定监�记录注册日志事务�交�执行��数�一致性 TransactionalEventListener(phase TransactionPhase.AFTER_COMMIT) public void recordRegisterLog(UserRegisteredEvent event) { // 模拟日志记录�际写入数�库或日志框� System.out.println(�事务绑定任务】事务�交�记录用户[ event.getUserId() ]注册日志用户� event.getUsername()); } }
5 测试验�
3.
1 测试æ�¥å�£UserControllerimport org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; RestController RequestMapping(/api/user) public class UserController { Autowired private UserService userService; Autowired private UserRepository userRepository; // 注册æ�¥å�£æ�¥æ”¶JSONå�‚æ•° PostMapping(/register) public String register(RequestBody User user) { // æ ¡éªŒç”¨æˆ·å��是å�¦å·²å˜åœ¨ if (userRepository.existsByUsername(user.getUsername())) { return 用户å��å·²å˜åœ¨; } userService.register(user); return 注册æˆ�功已触å�‘å��ç»ä»»åŠ¡; } }
3.
2 测试æ¥éª¤ä¸�预期结æ�œå�¯åŠ¨åº”ç”¨è®¿é—®H2æ�§åˆ¶å�°http://localhost:8080/h2-console验è¯�æ•°æ�®åº“表结æ�„通过Postman/curl调用æ�¥å�£curl -X POST http://localhost:8080/api/user/register-H “Content-Type: application/jsonâ€�-d ‘{“usernameâ€�:“zhangsanâ€�,“emailâ€�:“zhangsantest.comâ€�,“passwordâ€�:“123456â€�}’预期日志顺åº�体ç�°å�Œæ¥ã€�异æ¥ã€�事务绑定差异用户[zhangsan]注册æˆ�功ID1æ ¸å¿ƒä¸šåŠ¡æ‰§è¡Œã€�å�Œæ¥ä»»åŠ¡ã€‘å�‘é€�欢è¿�邮件给用户[zhangsan]邮箱zhangsantest.comå�Œæ¥é˜»å¡�ã€�事务绑定任务】事务æ��交å��记录用户[1]注册日志事务æ��交å��触å�‘ã€�异æ¥ä»»åŠ¡ã€‘å�‘æ”¾æ–°äººä¼˜æƒ åˆ¸ç»™ç”¨æˆ·[1]线程å��EventAsync-1异æ¥é��阻å¡�。事务å›�滚验è¯�在UserServiceå�‘布事件å‰�抛出异常观察事务å›�滚事务绑定任务ä¸�执行。
6 扩展场景æ�¡ä»¶ç›‘å�¬é€šè¿‡conditionå±�性å®�ç�°æ�¡ä»¶è¿‡æ»¤ä»…对特定用户触å�‘逻辑如ä¼�业邮箱用户// 仅当用户邮箱为ä¼�业邮箱时触å�‘ EventListener(condition #event.email.endsWith(company.com)) public void sendVipWelcomeMessage(UserRegisteredEvent event) { System.out.println(ã€�VIP专å±�】å�‘é€�ä¼�业用户欢è¿�消æ�¯ç”¨æˆ· event.getUsername()); }å››ã€�生产ç�¯å¢ƒæ³¨æ„�事项事件ä¸�å�¯å�˜äº‹ä»¶å—段设为final并通过æ�„é€ å™¨åˆ�始化é�¿å…�监å�¬è¿‡ç¨‹ä¸æ•°æ�®è¢«ç¯¡æ”¹å¯¼è‡´é€»è¾‘å¼‚å¸¸å¹‚ç‰æ€§è®¾è®¡ç›‘å�¬å™¨å�¯èƒ½å› é‡�试ã€�异æ¥å»¶è¿Ÿé‡�å¤�处ç�†éœ€é€šè¿‡â€œç”¨æˆ·ID业务类å�‹â€�å�šå¹‚ç‰æ ¡éªŒå¦‚æ•°æ�®åº“唯一索引ã€�ç¼“å˜æ ‡è®°é�¿å…�循ç�¯å�‘布ç¦�æ¢åœ¨ç›‘å�¬å™¨ä¸å�‘布å�Œç±»äº‹ä»¶é˜²æ¢æ»å¾ªç�¯è€—尽系统资æº�异常处ç�†å�Œæ¥åœºæ™¯ä¸‹ç›‘å�¬å™¨å¼‚常会阻æ–å�‘布者æµ�程需主动æ�•è�·å¼‚æ¥åœºæ™¯å¼‚常默认ä¸�ä¼ æ’需通过AsyncUncaughtExceptionHandler统一处ç�†ä¸�滥用事件仅
个副线逻辑的简å�•ä¸šåŠ¡æ— éœ€å¼•å…¥äº‹ä»¶é�¿å…�å¢�åŠ ç³»ç»Ÿå¤�æ�‚度适用äº�多组件è�”动ã€�需扩展的场景。五ã€�å¾®æœ�务ä¸Spring事件模å¼�的适é…�方案微æœ�务æ�¶æ�„下Spring事件并é��ä¸�å�¯ç”¨æ ¸å¿ƒè¾¹ç•Œæ˜¯ä»…适用äº�å�•æœ�务内解耦跨æœ�务通信需结å�ˆMQ补充形æˆ�“å�•æœ�务内事件跨æœ�务MQâ€�的混å�ˆæ¨¡å¼�兼顾轻é‡�解耦ä¸�分布å¼�å�¯é� 性。
1 å�•æœ�åŠ¡å†…å¸¸è§„ä½¿ç”¨æ ¸å¿ƒåœºæ™¯å�•个微æœ�务节点如用户æœ�务ã€�订å�•æœ�务内部的组件通信用法ä¸�å�•ä½“åº”ç”¨ä¸€è‡´ç›®æ ‡æ˜¯è§£è€¦æœ�务内模å�—Controllerã€�Serviceã€�Listenerä¸�ä¾�赖外部ä¸é—´ä»¶ã€‚
5.
1 使用è¦�点适用场景æœ�务内副线逻辑è�”动如注册å��更新本地缓å˜ã€�è®°å½•æœ¬åœ°æ—¥å¿—æ— éœ€è·¨æœ�务交互注æ„�事项多å®�例部署时事件仅在å�‘布å®�ä¾‹å†…ä¼ æ’å…¶ä»–å®�ä¾‹æ— æ³•æ„ŸçŸ¥éœ€ç»“å�ˆä¸šåС容å¿�åº¦é€‰æ‹©ä¼˜åŠ¿æ— ç½‘ç»œå¼€é”€ã€�è½»é‡�高效ä¸�å¢�åŠ å¾®æœ�务æ�¶æ�„å¤�æ�‚度。
2 è·¨æœ�务通信适é…�关键补充微æœ�务跨æœ�务è�”动如用户注册å��é€šçŸ¥ä¼˜æƒ åˆ¸æœ�务需通过“Spring事件MQâ€�å®�ç�°æ ¸å¿ƒæ€�路用MQ承æ�¥è·¨æœ�务消æ�¯ç›®æ ‡æœ�务消费MQå��触å�‘自身Spring事件处ç�†ä¿�æŒ�消费端内部分解耦。
5.
1 å®�ç�°æµ�程å�‘布端用户æœ�务注册æˆ�功å��å�Œæ—¶å�‘布本地事件处ç�†æœ�务内逻辑和MQ消æ�¯é€šçŸ¥è·¨æœ�务MQä¼ è¾“é€šè¿‡MQå®�ç�°è·¨æœ�务数æ�®ä¼ 递利用æŒ�久化ã€�é‡�试机制ä¿�éšœå�¯é� æ€§æ¶ˆè´¹ç«¯ä¼˜æƒ åˆ¸æœ�务监å�¬MQ消æ�¯æ¶ˆè´¹æˆ�功å��å�‘布本地事件触å�‘å�‘券ã€�日志ç‰é€»è¾‘。
5.