Java设计模式-观察者模式-SpringBoot实现
观察者模式
-
- 项目:https://gitee.com/KakarottoChen/blog-code.git
的:JavaSpringListener
- 项目:https://gitee.com/KakarottoChen/blog-code.git
一、Java观察者模式
Java观察者模式是一种设计模式,用于实现对象之间的一对多依赖关系。在观察者模式中,当一个对象的状态发生变化时,它的所有依赖对象(观察者)都会自动收到通知并进行相应的更新。
观察者模式由以下几个核心组件组成:
- 主题(Subject):也称为被观察者或可观察对象,它维护一组观察者对象,并提供方法用于添加、删除和通知观察者。
- 观察者(Observer):也称为订阅者或监听器,它定义了接收和处理主题通知的方法。
- 具体主题(ConcreteSubject):实现主题接口,维护观察者列表,并在状态发生变化时通知观察者。
- 具体观察者(ConcreteObserver):实现观察者接口,定义了接收和处理主题通知的具体逻辑。
观察者模式的工作流程如下:
- 观察者通过订阅主题来注册自己,使得主题知道它们的存在。
- 当主题的状态发生变化时,它会通知所有注册的观察者。
- 观察者收到通知后,根据需要进行相应的更新操作。
观察者模式的优点包括解耦主题和观察者,使得它们可以独立变化;支持动态添加和删除观察者;实现了对象之间的松耦合,提高了系统的灵活性和可扩展性。
- 场景1:用图来理解:
- 场景2:多模块开发,解耦情况下,可以模块之间传递参数。
二、Spring实现的观察者模式
1、设计理念
在Spring Boot中,实现观察者模式的设计理念是基于事件驱动的编程模型。Spring Boot提供了一种简单而强大的事件机制,可以方便地实现观察者模式。
以下是Spring Boot实现观察者模式的设计理念:
-
事件(Event):事件是触发的动作或状态变化,可以是任何Java对象。在Spring Boot中,事件通常是继承自ApplicationEvent类的对象。
-
事件发布者(Event Publisher):事件发布者负责发布事件。在Spring Boot中,可以使用ApplicationEventPublisher接口来发布事件。通常,事件发布者是一个Spring Bean,通过依赖注入ApplicationEventPublisher来发布事件。
-
事件监听者(Event Listener):事件监听者是观察者,负责接收和处理事件。在Spring Boot中,可以使用@EventListener注解标记方法,使其成为事件监听者。当事件发布者发布事件时,被标记的方法会自动被调用。
-
事件处理逻辑:事件监听者方法中定义了事件的处理逻辑。可以根据具体需求,在事件监听者方法中编写相应的业务逻辑。
通过使用Spring Boot的事件机制,可以实现松耦合的观察者模式。事件发布者和事件监听者之间没有直接的依赖关系,它们通过事件进行通信。这样,可以方便地添加、删除和修改事件监听者,而不需要修改事件发布者的代码。
观察者模式的设计理念在Spring Boot中体现了面向对象编程的原则,如单一职责、开闭原则和依赖倒置原则。它提供了一种灵活、可扩展和可维护的方式来实现事件驱动的编程模型。
2、继承ApplicationEvent和不继承的区别
- 发送的参数可以是普通JavaBean(String、integer、自定义类)、也可以是继承了ApplicationEvent的JavaBean
如果MyEvent继承ApplicationEvent,则可以使用Spring框架提供的事件传递机制。这意味着可以通过ApplicationEventPublisher发布事件,并且可以使用@EventListener注解标记观察者方法来接收事件。这种方式更符合Spring框架的设计理念,可以方便地实现观察者模式。 如果MyEvent不继承ApplicationEvent,则无法使用Spring框架提供的事件传递机制。需要自己实现事件的传递和观察者模式的逻辑。这种方式更适用于非Spring环境下的观察者模式实现。 继承ApplicationEvent的好处是可以利用Spring框架提供的事件传递机制,简化了观察者模式的实现。同时,还可以利用Spring框架提供的其他特性,如事务管理、AOP等。 不继承ApplicationEvent的好处是更加灵活,可以根据具体需求自由定义事件的结构和传递方式。但需要自己实现事件的传递和观察者模式的逻辑。 综上所述,如果在Spring框架中使用观察者模式,建议继承ApplicationEvent,以便利用Spring框架提供的事件传递机制和其他特性。
3、默认是广播模式
Spring框架中的观察者模式默认是广播模式。
在Spring框架中,当一个事件被发布时,所有注册的观察者都会接收到该事件。这意味着,一个事件可以被多个观察者同时接收和处理,实现了广播的效果。
这种广播模式的实现是通过ApplicationEventMulticaster接口和其默认实现类SimpleApplicationEventMulticaster来完成的。SimpleApplicationEventMulticaster会将事件广播给所有注册的观察者。
当然,如果需要更加细粒度地控制事件的传递方式,也可以自定义ApplicationEventMulticaster的实现类,实现自己的事件传递逻辑。
总结起来,Spring框架中的观察者模式默认是广播模式,一个事件会被所有注册的观察者接收和处理。这种广播模式的实现是通过ApplicationEventMulticaster接口和SimpleApplicationEventMulticaster类来完成的。
三、Spring实现
- 注意:监听者是异步执行的
1、广播模式(默认)——不推荐
- 事件 —— 这里先不用,也可以用
- 这里发送普通的JavaBean的参数,不发送“事件”
1.1、事件(Event)(无)
1.2、事件发布者(Event Publisher)
- 注入ApplicationEventPublisher来实现
package com.cc.jsl.service.impl; import com.cc.jsl.service.ILoginService; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.annotation.Resource; /** * <p>事件发布者(Event Publisher)</p> * * @author CC * @since 2023/10/10 */ @Service public class LoginServiceImpl implements ILoginService { @Resource private ApplicationEventPublisher eventPublisher; @Override public void login(){ //登陆逻辑... //发送 // 1、可以直接发送JavaBean的参数:如String、自定义类 eventPublisher.publishEvent("字符串参数!"); // eventPublisher.publishEvent(new UserCs("cs" , 18)); // eventPublisher.publishEvent(34); // 2、发送事件参数(继承了ApplicationEvent的类) } }
1.3、事件监听者(Event Listener)
- 使用@Async、@EventListener实现
- 可以是很多个,也可以在不同类中
package com.cc.jsl.listener; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; /** * <p>事件监听者(Event Listener)</p> * * @author CC * @since 2023/10/10 */ @Component public class ReceiveListener { /** * 打电话 - 接收普通JavaBean参数 */ @Async @EventListener public void sendCall(String msg) { //发送邮件逻辑 System.out.println("打电话!-普通-> " + msg); } /** * 发送邮件 - 接收字符串参数 */ @Async @EventListener public void sendEmail(String msg) { //发送邮件逻辑 System.out.println("发送邮件!-普通-> " + msg); } }
2、单个发送(推荐)
- 每个发送都自定义一个唯一的类,并且继承ApplicationEvent
2.1、事件(Event)
- 继承ApplicationEvent
- 继承ApplicationEvent的好处是可以利用Spring框架提供的事件传递机制,简化了观察者模式的实现。同时,还可以利用Spring框架提供的其他特性,如事务管理、AOP等。
package com.cc.jsl.event; import lombok.Getter; import lombok.Setter; import org.springframework.context.ApplicationEvent; /** * <p>发邮件专属的唯一事件</p> * <p>需要实现set方法</p> * * @author CC * @since 2023/10/10 */ @Getter @Setter public class EmailEvent extends ApplicationEvent { /** * 参数1 */ private String name; /** * 参数2 */ private Integer age; public EmailEvent(Object source, String name, Integer age) { super(source); this.name = name; this.age = age; } }
2.2、事件发布者(Event Publisher)
package com.cc.jsl.service.impl; import com.cc.jsl.event.EmailEvent; import com.cc.jsl.service.ILoginService; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import javax.annotation.Resource; /** * <p>事件发布者(Event Publisher)</p> * * @author CC * @since 2023/10/10 */ @Service public class LoginServiceImpl implements ILoginService { @Resource private ApplicationEventPublisher eventPublisher; @Override public void login(){ //登陆逻辑... //事件发布 // 1、可以直接发送JavaBean的参数:如String、自定义类 // eventPublisher.publishEvent("字符串参数!"); // eventPublisher.publishEvent(new UserCs("cs" , 18)); // eventPublisher.publishEvent(34); // 2、发送事件参数(继承了ApplicationEvent的类) EmailEvent emailEvent = new EmailEvent(this, "cc", 18); eventPublisher.publishEvent(emailEvent); } }
2.3、事件监听者(Event Listener)
package com.cc.jsl.listener; import com.cc.jsl.event.EmailEvent; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; /** * <p>事件监听者(Event Listener)</p> * * @author CC * @since 2023/10/10 */ @Component public class ReceiveListener { /** * 打电话 - 接收普通JavaBean参数 */ @Async @EventListener public void sendCall(String msg) { //发送邮件逻辑 System.out.println("打电话!-普通-> " + msg); } /** * 发送邮件 - 接收字符串参数 */ @Async @EventListener public void sendEmail(String msg) { //发送邮件逻辑 System.out.println("发送邮件!-普通-> " + msg); } /** * 发送邮件 - 接收唯一事件 */ @Async @EventListener(EmailEvent.class) public void sendEmail(EmailEvent emailEvent) { //发送邮件逻辑 System.out.println("发送邮件!-事件-> " + emailEvent); } }
- 发送邮件!-事件-> 除了这个以外的所有监听者都不会监听到消息
- 经过测试,不使用事件,直接使用自定义类,只有监听了这个类的接受者才能接收到,所以相当于实现了一对一。
- 自定义事件的好处:可以利用Spring框架提供的事件传递机制,简化了观察者模式的实现。同时,还可以利用Spring框架提供的其他特性,如事务管理、AOP等。
- 接收到的消息:
四、总结
参考:https://blog.csdn.net/weixin_43745998/article/details/127301003
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!