• 观察者模式之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. 总结:设计模式很流弊。。。。。。。。
  • 相关阅读:
    Redis 集合(Set)
    北京Uber优步司机奖励政策(1月21日)
    成都Uber优步司机奖励政策(1月21日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(1月21日)
    全国各城市Uber客服联系方式(电话、邮箱、微博)
    成都Uber优步司机奖励政策(1月20日)
    北京Uber优步司机奖励政策(1月20日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(1月20日)
    Linq聚合函数使用
    Linq查询案例
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/16669083.html
Copyright © 2020-2023  润新知