观察者模式之EventBus(转载)
转载:https://zhuanlan.zhihu.com/p/434087470
一、EventBus简介
EventBus是一种用于Android的事件发布订阅模式(观察者模式),由GreenRobot开发,Gihub地址是:EventBus。它简化了应用程序内各个组件之间进行通信的复杂度,尤其是碎片之间进行通信的问题,可以避免由于使用广播通信而带来的诸多不便。【EventBus_百度百科】
突然发现百度百科,写的比我写的好。。。。
二、上代码
通过EventBus异步分发请求。
1、导入依赖
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>28.1-jre</version> </dependency>
2、创建EventBus的Bean
@Configuration public class Config { @Bean public AsyncEventBus asyncEventBus() { ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("asyncEventBus").build(); ExecutorService executorService = new ThreadPoolExecutor(5, 10, 10000L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(64), namedThreadFactory, new ThreadPoolExecutor.CallerRunsPolicy()); return new AsyncEventBus(executorService); } @Bean public EventBus eventBus() { return new EventBus(); } }
3、注册分发处理类
@Component public class EventListener { private static final Logger logger = LoggerFactory.getLogger(EventListener.class); private ConcurrentHashMap<String, List<EventHandler>> enumMap = new ConcurrentHashMap<String, List<EventHandler>>(); @Resource private EventBus eventBus; @Resource private AsyncEventBus asyncEventBus; /** * 注册eventBus */ @PostConstruct public void init() { eventBus.register(this); asyncEventBus.register(this); } public void register(String eventType, EventHandler eventHandler) { logger.info("注册事件处理器,type={}", eventType); enumMap.computeIfAbsent(eventType, k -> new ArrayList<>()); enumMap.get(eventType).add(eventHandler); } /** * 事件处理器 * 注意:eventBus源码中有四种方法的实现,分别代表不同的功能 * @param eventMsg */ @Subscribe @AllowConcurrentEvents public void onEvent(EventMsg eventMsg) { execute(eventMsg); } /** * 分发请求 * * @param eventMsg */ public void execute(EventMsg eventMsg) { List<EventHandler> lists = enumMap.get(eventMsg.getEventTypeEnum().name()); if (lists == null) { logger.error("事件没有对应的Handler,event:{}", eventMsg.toString()); return; } for (EventHandler eventHandler : lists) { eventHandler.execute(eventMsg); } } /** * 发送请求 * @param event */ public void post(EventMsg event) { try { asyncEventBus.post(event); } catch (Exception e) { logger.error("asyncEventBus.post()异常,event:{}", event.toString()); } } }
4、事件类型
public enum EventTypeEnum { ITEM("产品"), CLASS("类别"), SPECIFICATION("规格"), SERVICE("服务"), ADDRESS("地址") ; private String description; EventTypeEnum(String description) { this.description = description; } public String getDescription() { return description; } }
5、Handler事件处理器
/** * 事件处理器 */ public interface EventHandler { /** * 事件执行 * * @param event * @return */ boolean execute(EventMsg event); } /** * 类别事件处理器 */ @Slf4j @Component public class ClassHandler implements EventHandler { @Autowired private EventListener eventListener; @PostConstruct public void register() { eventListener.register(EventTypeEnum.CLASS.name(), this); } @Override public boolean execute(EventMsg event) { log.info("我是分类处理器!"); return false; } } /** * 产品事件处理器 */ @Slf4j @Component public class ItemEventHandler implements EventHandler { @Autowired private EventListener eventListener; @PostConstruct public void register() { eventListener.register(EventTypeEnum.ITEM.name(), this); } @Override public boolean execute(EventMsg event) { try { //测试请求是异步的~~~~时间大家可以设置小一点~~~ Thread.sleep(50000); log.info("我是产品处理器!"); return false; } catch (Exception e) { log.error("产品处理失败",e); } return true; } }
6、消息类
@Data @Builder public class EventMsg { private String content; private EventTypeEnum eventTypeEnum; private boolean async; }
7、测试
@Slf4j @Controller public class ItemDemoController { @Resource private EventListener eventListener; @ResponseBody @RequestMapping("/list") public Result getItemList() { System.out.println("获取产品列表开始!"); EventMsg msg = EventMsg.builder() .content("111111111") .async(true) .eventTypeEnum(EventTypeEnum.ITEM) .build(); eventListener.post(msg); System.out.println("111111"); return new Result("1", "获取产品列表成功", "111"); } }
8、测试结果
9、解释
- 通过@Configuration 注册EventBus的bean,通过@Resource注入进 EventListener。
- 通过注册@PostConstruct实现两个目的:第一个目的:项目启动后注册观察者到EventBus中。第二个目的:加载处理类的类型,即将Handler事件处理类注册进入EventListener的ConcurrentHashMap中,以作后续分发使用
- 通过注册@Subscribe确定事件处理器,当使用 asyncEventBus.post(event)或者 eventBus.post(event)发送消息时,会触发当前注解所在的方法,进行消息EventMsg的处理。所以EventBus.post()发完消息实际相当于在当前方法中调用了定义方法,还是会继续同步处理消息的。只有AsyncEventBus.post才会异步处理消息。
- EventListener#execute 方法专门进行事件分发。通过消息EventMsg的eventTypeEnum属性,通过ConcurrentHashMap获取注册的事件处理器,执行EventHandler的子类的excecute方法。
- 最后就是很无趣的,测试类,组装EventMsg,通过EventListener.post(……)发送消息。注意eventTypeEnum的事件类型,不同的事件类型会分发到不同的Handler中!!!
- 结果显示,因为咱们在ItemHandler中设置了Thread.sleep(50000),所以最后打印的结果可以看出asyncEventBus是异步的。如果使用的是 eventBus.post(……)那就是同步的了。
- 总结:设计模式很流弊。。。。。。。。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2021-09-08 springboot公共接口接收json数据