强化学习数学原理:从测度论到策略梯度的工程化验证
2026/10/15 14:40:05
视频看了几百小时还迷糊?关注我,几分钟让你秒懂!(发点评论可以给博主加热度哦)
想象你在开发一个用户注册系统,注册成功后要:
@Service public class UserService { public void register(User user) { // 1. 保存用户 userRepository.save(user); // 2. 发邮件 emailService.sendWelcomeEmail(user.getEmail()); // 3. 发短信 smsService.sendVerificationCode(user.getPhone()); // 4. 记日志 logService.log("用户注册", user.getId()); // 5. 初始化积分 pointService.initPoints(user.getId()); // 6. 推送企业微信 wechatService.pushRegisterMessage(user.getName()); } }🚨问题爆炸:
这就是典型的“高耦合”代码!
Spring 事件监听 = 观察者模式 + Spring 容器管理
它允许你:发布一个事件,所有关心这个事件的组件自动响应,彼此完全解耦!
就像你发朋友圈:
// 继承 ApplicationEvent(Spring 4.2+ 后可省略,但建议保留) public class UserRegisteredEvent extends ApplicationEvent { private final User user; public UserRegisteredEvent(Object source, User user) { super(source); this.user = user; } public User getUser() { return user; } }💡
source通常是发布事件的对象(如当前 Service),可用于追踪来源。
@Service public class UserService { // 注入 Spring 的事件发布器 @Autowired private ApplicationEventPublisher eventPublisher; public void register(User user) { // 1. 保存用户(核心逻辑) userRepository.save(user); // 2. 发布事件!后续操作全部解耦 eventPublisher.publishEvent(new UserRegisteredEvent(this, user)); } }✅关键:注册方法现在只做“注册”,其他事交给监听器!
@Component public class EmailListener { @EventListener // ←←← 核心注解! public void handleUserRegistered(UserRegisteredEvent event) { User user = event.getUser(); System.out.println("【邮件服务】发送欢迎邮件给: " + user.getEmail()); // emailService.send(...); } }@Component public class SmsListener { @EventListener public void handleUserRegistered(UserRegisteredEvent event) { User user = event.getUser(); System.out.println("【短信服务】发送验证码到: " + user.getPhone()); // smsService.send(...); } }@Component public class LogListener { @EventListener public void handleUserRegistered(UserRegisteredEvent event) { User user = event.getUser(); System.out.println("【日志服务】记录用户注册: " + user.getId()); // logService.log(...); } }✅优势:
- 每个监听器职责单一;
- 新增“发优惠券”?只需写一个新监听器,注册逻辑一行都不用改!
默认事件是同步的(监听器执行完才返回)。如果发邮件很慢,用户要等很久!
✅ 解决方案:加@Async
@Component public class AsyncEmailListener { @EventListener @Async // ←←← 开启异步(需在启动类加 @EnableAsync) public void handleUserRegistered(UserRegisteredEvent event) { // 模拟耗时操作 try { Thread.sleep(3000); } catch (Exception e) {} System.out.println("【异步邮件】发送完成!"); } }⚠️ 注意:在
Application.java上加@EnableAsync!
@EventListener(condition = "#event.user.vip == true") public void handleVipUserRegistered(UserRegisteredEvent event) { System.out.println("【VIP 专属】发送豪华礼包!"); }使用 SpEL 表达式,灵活过滤。
Spring 自己也会发布事件,比如容器启动完成:
@Component public class StartupListener { @EventListener public void onContextRefreshed(ContextRefreshedEvent event) { System.out.println("【系统启动】应用已初始化完毕!"); // 可用于加载缓存、预热数据等 } }常用内置事件:
| 事件 | 触发时机 |
|---|---|
ContextRefreshedEvent | ApplicationContext 初始化或刷新完成 |
ContextClosedEvent | ApplicationContext 关闭 |
RequestHandledEvent | Web 请求处理完成 |
| 方案 | 耦合度 | 扩展性 | 异常处理 | 可测试性 |
|---|---|---|---|---|
| 直接调用(反例) | 高(UserService 依赖所有服务) | 差(改核心代码) | 全局回滚 | 难(要 mock 所有) |
| 事件监听(正例) | 零耦合 | 极好(加监听器即可) | 独立失败不影响主流程 | 每个监听器单独测 |
💡特别提醒:
如果某个监听器失败(比如邮件服务挂了),不会影响其他监听器和主流程!
(除非你手动抛异常并配置了事务回滚)
src/main/java ├── event/ │ └── UserRegisteredEvent.java ├── listener/ │ ├── EmailListener.java │ ├── SmsListener.java │ └── LogListener.java ├── service/ │ └── UserService.java └── Application.java // 加 @EnableAsync@SpringBootApplication @EnableAsync // 开启异步支持 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }@RestController public class TestController { @Autowired private UserService userService; @PostMapping("/register") public String register(@RequestBody User user) { userService.register(user); return "注册成功!后续操作已异步执行。"; } }调用:
POST /register { "name": "张三", "email": "zhangsan@example.com", "phone": "13800138000" }控制台输出:
注册成功!后续操作已异步执行。 【日志服务】记录用户注册: 1 【短信服务】发送验证码到: 13800138000 【异步邮件】发送完成!final字段 + 构造函数初始化。@Component public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler { @Override public void handleUncaughtException(Throwable ex, Method method, Object... params) { System.err.println("异步监听器异常: " + ex.getMessage()); } }@Transactional,监听器默认在同一事务中;@TransactionalEventListener。| 场景 | 传统写法 | 事件监听 |
|---|---|---|
| 用户注册后发邮件 | UserService 直接调 EmailService | UserService 发事件,EmailListener 监听 |
| 订单支付后更新库存 | OrderService 调 InventoryService | OrderService 发事件,InventoryListener 监听 |
| 系统启动加载缓存 | 在 main 方法里写 | 监听 ContextRefreshedEvent |
✅记住:
“我不关心谁来处理,我只负责通知” —— 这就是事件驱动的魅力!
视频看了几百小时还迷糊?关注我,几分钟让你秒懂!(发点评论可以给博主加热度哦)