观察者模式之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、解释

  1. 通过@Configuration 注册EventBus的bean,通过@Resource注入进 EventListener。
  2. 通过注册@PostConstruct实现两个目的:第一个目的:项目启动后注册观察者到EventBus中。第二个目的:加载处理类的类型,即将Handler事件处理类注册进入EventListener的ConcurrentHashMap中,以作后续分发使用
  3. 通过注册@Subscribe确定事件处理器,当使用 asyncEventBus.post(event)或者 eventBus.post(event)发送消息时,会触发当前注解所在的方法,进行消息EventMsg的处理。所以EventBus.post()发完消息实际相当于在当前方法中调用了定义方法,还是会继续同步处理消息的。只有AsyncEventBus.post才会异步处理消息。
  4. EventListener#execute 方法专门进行事件分发。通过消息EventMsg的eventTypeEnum属性,通过ConcurrentHashMap获取注册的事件处理器,执行EventHandler的子类的excecute方法。
  5. 最后就是很无趣的,测试类,组装EventMsg,通过EventListener.post(……)发送消息。注意eventTypeEnum的事件类型,不同的事件类型会分发到不同的Handler中!!!
  6. 结果显示,因为咱们在ItemHandler中设置了Thread.sleep(50000),所以最后打印的结果可以看出asyncEventBus是异步的。如果使用的是 eventBus.post(……)那就是同步的了。
  7. 总结:设计模式很流弊。。。。。。。。
posted @   Mars.wang  阅读(131)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
历史上的今天:
2021-09-08 springboot公共接口接收json数据
点击右上角即可分享
微信分享提示