游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

说下你可能没用过的EventBus

  最近在CodeReview的时候发现了这样一个业务场景,某个业务处理完成之后需要通知审核人员,通知的方式包含短信和邮件,所以代码大致是这样:业务校验validate();处理业务逻辑doBusiness();发送邮件或者发送其他类型消息sendMsg();
  这个对不对呢?
  基于这种普遍的业务场景来说,一般首先我们会考虑同步或者异步发送的问题。
  同步的话对接口RT有影响,而且和业务逻辑耦合在一起,这样的做法肯定不太好。
  一般情况下,我们会做成异步的方式,使用MQ自己发送自己消费,或者说一个线程池搞定,这样的话不影响主业务逻辑,可以提高性能,并且代码做到了解耦。
  然后还有就是数据一致性的问题,邮件一定要发送成功吗?
  大多数时候其实我们并不要求邮件一定100发送成功,失败了就失败好了,监控告警打点做好失败率不要超过阈值就好,还有就是消息服务一旦收到请求应该自己保证消息能够投递。
  所以总的来说,使用MQ发送消息自己消费处理,或者线程池异步处理,最后自己搞个补偿的逻辑就能处理好这类问题。
  那么,今天要说的是这两个解决方案之外的处理方式,对于这种场景其实我们可以用EventBus来解决。EventBus使用
  看名字就知道,EventBus是事件总线的意思,它是GoogleGuava库的一个工具,基于观察者模式可以做到进程内的代码解耦作用。
  就拿上面的例子来说,引入一个MQ太重了,其实不太需要这样做,EventBus也能达到这个效果,和MQ相比他只能提供进程内的消息事件传递,这对于我们这种业务场景来说足够了不是吗?
  我们先看EventBus怎么来使用,一般先创建一个EventBus实例。1。创建EventBusprivatestaticEventBuseventBusnewEventBus();
  第二步,创建一个事件消息订阅者,处理方式非常简单,只要在我们希望去处理事件的方法上加上Subscribe注解即可。
  形参只能有一个,如果定义0个或者多个的话运行就会报错。publicclassEmailMsgHandler{Subscribepublicvoidhandle(LongbusinessId){System。out。println(sendemailmsgbusinessId);}}
  第三步,注册事件。eventBus。register(newEmailMsgHandler());
  第四步,发送事件。eventBus。post(1L);
  这就是一个EventBus使用的最简单例子,下面我们看看结合开头说的例子怎么处理。结合实际
  比如上面说的案例,举例来说比如注册和用户下单的场景,都需要发送消息和邮件给用户。
  EventBus并不强制说我们一定要用单例模式,因为他的创建销毁成本比较低,所以更多是根据我们的业务场景和上下文自己来选择。publicclassUserService{privatestaticEventBuseventBusnewEventBus();publicvoidregist(){LonguserId1L;eventBus。register(newEmailMsgHandler());eventBus。register(newSmsMsgHandler());eventBus。post(userId);}}publicclassBookingService{privatestaticEventBuseventBusnewEventBus();publicvoidbooking(){业务逻辑LongbookingId2L;eventBus。register(newEmailMsgHandler());eventBus。register(newSmsMsgHandler());eventBus。post(bookingId);}}
  然后在业务逻辑处理完成之后,分别去注册了邮件和短信两个事件订阅者。publicclassEmailMsgHandler{Subscribepublicvoidhandle(LongbusinessId){System。out。println(sendemailmsgbusinessId);}}publicclassSmsMsgHandler{Subscribepublicvoidhandle(LongbusinessId){System。out。println(sendsmsmsgbusinessId);}}
  最后我们发送事件,用户注册我们发送了一个用户ID,下单成功我们发送了一个订单ID。
  再写一个测试类去测试一下,分别创建两个service,然后分别调用方法。publicclassEventBusTest{publicstaticvoidmain(String〔〕args){UserServiceuserServicenewUserService();userService。regist();BookingServicebookingServicenewBookingService();bookingService。booking();}}
  执行测试类,我们可以看到输出,分别去执行了我们的事件订阅的方法。sendemailmsg1sendsmsmsg1sendemailmsg2sendsmsmsg2
  使用起来你会发现非常简单,对于希望轻量级简单地做到解耦使用EventBus非常合适。注意别踩坑
  首先,注意一下例子中的参数都是Long类型,如果事件的参数是其他类型的话,那么消息是无法接受到的,比如我们把下单中发送的订单ID改成String类型然后会发现没有消费了,因为我们没有定义一个参数类型是String的方法。publicclassBookingService{privatestaticAsyncEventBuseventBusnewAsyncEventBus(Executors。newFixedThreadPool(3));publicvoidbooking(){业务逻辑StringbookingId2;eventBus。register(newEmailMsgHandler());eventBus。register(newSmsMsgHandler());eventBus。post(bookingId);}}输出sendemailmsg1sendsmsmsg1
  去EmailMsgHandler和SmsMsgHandler都新增一个接收String类型的订阅方法,这样就可以接收到了。Subscribepublicvoidhandle(StringbusinessId){System。out。println(sendemailmsgforstringbusinessId);}Subscribepublicvoidhandle(StringbusinessId){System。out。println(sendsmsmsgforstringbusinessId);}输出sendsmsmsg1sendemailmsg1sendemailmsgforstring2sendsmsmsgforstring2
  除此之外,其实我们可以定义一个DeadEvent来处理这种情况,它相当于是一个默认的处理方式,当没有匹配的事件类型参数的话就会默认发送一个DeadEvent事件。
  定义一个默认处理器。publicclassDefaultEventHandler{Subscribepublicvoidhandle(DeadEventevent){System。out。println(nosubscriber,event);}}
  给BookingService新增一个pay()支付方法,下单完了去支付,注册我们的默认事件。publicvoidpay(){业务逻辑eventBus。register(newDefaultEventHandler());eventBus。post(newPayment(UUID。randomUUID()。toString()));}ToStringDataNoArgsConstructorAllArgsConstructorpublicclassPayment{privateStringpaymentId;}
  执行测试bookingService。pay()看到输出结果:nosubscriber,DeadEvent{sourceAsyncEventBus{default},eventPayment(paymentId255da94271284bd1bacaf0a8e569ed88)}源码分析
  OK,简单的介绍就到这里,那其实到目前为止我们说的这个都是同步调用的,这不太符合我们的要求,我们当然使用异步处理更好。
  那就看看源码它是怎么实现的。BetapublicclassEventBus{privatestaticfinalLoggerloggerLogger。getLogger(EventBus。class。getName());privatefinalStringidentifier;privatefinalExecutorexecutor;privatefinalSubscriberExceptionHandlerexceptionHandler;privatefinalSubscriberRegistrysubscribersnewSubscriberRegistry(this);privatefinalDispatcherdispatcher;publicEventBus(){this(default);}publicEventBus(Stringidentifier){this(identifier,MoreExecutors。directExecutor(),Dispatcher。perThreadDispatchQueue(),LoggingHandler。INSTANCE);}}
  identifier就是个名字,标记,默认就是default。
  executor执行器,默认创建一个MoreExecutors。directExecutor(),事件订阅者根据你自己提供的executor来决定如何执行事件订阅的处理方式。
  exceptionHandler是异常处理器,默认创建的就是打点日志。
  subscribers就是我们的消费者,订阅者。
  dispatcher用来做事件分发。
  默认创建的executor是一个MoreExecutors。directExecutor(),看到command。run()你就会发现他这不就是同步执行嘛。publicstaticExecutordirectExecutor(){returnDirectExecutor。INSTANCE;}privateenumDirectExecutorimplementsExecutor{INSTANCE;Overridepublicvoidexecute(Runnablecommand){command。run();}OverridepublicStringtoString(){returnMoreExecutors。directExecutor();}
  同步执行还是不太好,我们希望不光给我们解耦,还要异步执行,EventBus给我们提供了AsyncEventBus,Executor我们自己传入就好了。publicclassAsyncEventBusextendsEventBus{publicAsyncEventBus(Stringidentifier,Executorexecutor){super(identifier,executor,Dispatcher。legacyAsync(),LoggingHandler。INSTANCE);}publicAsyncEventBus(Executorexecutor,SubscriberExceptionHandlersubscriberExceptionHandler){super(default,executor,Dispatcher。legacyAsync(),subscriberExceptionHandler);}publicAsyncEventBus(Executorexecutor){super(default,executor,Dispatcher。legacyAsync(),LoggingHandler。INSTANCE);}
  上面的代码我们改成异步的,这样不就好起来了嘛,这样的话,实际上可以结合我们自己的线程池来处理了。privatestaticAsyncEventBuseventBusnewAsyncEventBus(Executors。newFixedThreadPool(3));
  OK,这个说清楚了,我们可以顺便再看看事件分发的处理,看到DeadEvent了吧,没有当前事件的订阅者,就会发送一个DeadEvent事件,bingo!publicvoidpost(Objectevent){IteratorSubscribereventSubscriberssubscribers。getSubscribers(event);if(eventSubscribers。hasNext()){dispatcher。dispatch(event,eventSubscribers);}elseif(!(eventinstanceofDeadEvent)){theeventhadnosubscribersandwasnotitselfaDeadEventpost(newDeadEvent(this,event));}}总结
  OK,这个使用和源码还是比较简单的哈,有兴趣的同学可以自己去瞅瞅,花不了多少工夫。
  总的来说,EventBus就是提供了我们一个更优雅的代码解耦的方式,实际工作中的业务你肯定能用上它!

杨颖手撕宋雨琦,杨颖在娱乐圈的地位是否离开黄晓明就一落千丈?baby这一次跟宋雨琦的撕,让我再一次见识到了娱乐圈的现实。当初跟黄晓明世纪婚礼的时候,半个娱乐圈的人都来捧场了,那时候的baby,虽然也没有拿得出手的作品,但依然被媒体……月消费80万?李湘嫁进去的豪门,只不过是自己扛下了所有东西月消费80万?李湘嫁进去的豪门,只不过是自己扛下了所有提起嫁入豪门的女星,李湘绝对是首当其冲。首先是她的身份,作为曾经的主持一姐,到后来的飞流直下三千尺,离不开她的……古装男神落泪合集,朱一龙最唯美,罗云熙最让人心碎古装影视作品中的女神哭,惹人心疼,男神哭的时候,也不差,也能引起观众共鸣。今天小编为你盘点一下,影视作品中,男神落泪的瞬间。朱一龙知否知否中的小公爷,芝兰玉树的性子……过目不忘的好演员消失的小巩俐,发光的周显欣!有些演员,可能没有巨大流量包裹其成为明星,也可能没有巨大关注推动其成为名人,甚至可能连名字都鲜有人知道,但当你看过他们的作品,便会迅速达成一个这样的共识:他们是好演员。好……爱奇艺取消超前点播模式,大力推广星钻,不开你就没得看之前爱奇艺付费超前点播的事情闹的沸沸扬扬,原本就是资本家为了赚钱弄出来的套路,你想先看到后面的剧情,然后又不在乎那几块钱的话,完全就可以选择超前点播,记得当时我在《庆余年》也超……又一新区崛起,北京多所名校有意离家出走,教育C位或将难保北京作为我国教育中心,享受着得天独厚的优势,不仅高校林立,还坐拥各种资源,让其他城市难以望其项背。不过随着北京人口增多,面临资源紧缺的尴尬境遇,为了解决这一问题,相关部门……娱乐圈小花疯狂内卷!刘浩存资源逆天,张子枫强势霸屏大银幕现在内卷一词很流行,在各行各业都存在这种声音,更不用说更新换代飞速的娱乐圈了。贵圈内卷到底有多严重?85后花旦还在深耕电视剧,95后小花没来得及站稳脚跟,00后新生代小花……把王思聪撕上热搜的她,恐怕会反转已经800年没见过什么惊天动地的大瓜,能一口气上五六七八个热搜了一晚上都在被王思聪和孙一宁刷屏热搜,24小时滚动更新,热搜前十,他俩恨不得占了一半孙一宁到底是谁?什……迪士尼理论海洋奇缘莫阿娜公主的真实身份大家好,今天笔者打算从不同的角度解读一部动画电影,迪士尼2016年推出的《海洋奇缘》。本片承袭了迪士尼动画工作室一贯的制作水准,无论视觉效果还是人物刻画都无可挑剔,配乐和迪士尼……R1SE成员任豪再发声明,删除微博不是本人愿意,让祖国帮助日刚刚R1SE成员任豪再次发出微博,删除微博不是本人愿意,如果你的冷嘲热讽能唤起大家的重视骂骂我也挺好又引发网友热议,很多网友都是在评论区留言说任豪抖机灵日本福岛核辐射问题……沪上皇秦奋的奢靡人生你勤奋不一定有钱,但他秦奋一定有钱都说撒娇的女人最好命,有钱的男人最幸运。有些人,天生注定是上等命,含着金汤匙出生,生来就赢在起跑线上。他什么事情都不用干,就能不费吹灰之力得到想要的一切,人家都想着……欧弟宣布离婚,和前妻被指没夫妻相,节目中当众闹矛盾语气冷漠湖南卫视王牌节目有两个,一个是《快乐大本营》,一个是《天天向上》,这两个节目唯一的不同点就是快本的主持人还算是很稳定的,反倒是天天向上,到现在主持人也算是经历过‘大换血’了。不……
2018销量最好的杂志海清娜扎徐冬冬范冰冰胡一天春节已过完,在此期间,除了电影大片燃情吸睛之外,时尚杂志也是大众娱乐的项目之一,截止目前,2018销量最好的时尚杂志有海清的《精品购物指南》、古力娜扎的《时尚芭莎》、徐冬冬的《……SNH48孙珍妮演技受张柏芝力挺,直通星爷最终面试名单喜剧综艺《星星美人鱼》即将接近尾声,关于谁能一路闯关到最后见到星爷周星驰的猜测越来越多,到底是谁最终能一睹星爷风采,又是谁能幸运加入《美人鱼2》的拍摄,第十期节目中我们便能看出……赵英博清爽夏日写真曝光少年脸尽展温柔侧颜杀星关系6月5日讯今日,95后高颜值小生赵英博曝光一组清爽夏日写真,清新自然的造型,置身于绿意盎然的象山自然风景中,让人不经意联想起一幅幅青春剧的画面,少年身着白衫,纯粹无邪。柔……何超仪巴黎街拍又美又飒霸气演绎换装秀星关系3月3日讯何超仪及丈夫陈子聪日前由洛杉矶完成新片拍摄,即飞往巴黎,以品牌之友VIP的身份出席某品牌2020秋冬时装秀。除看秀外,何超仪在抵达巴黎后也一连换上多套造型,以巴……谢霆锋申请退出加拿大国籍不料蒋大为和董卿移民外籍中枪当谢霆锋做客央视电影频道,被质疑外籍身份时,他积极地回答了国籍问题:我出生在香港,所以我本来是中国人。事实上,我已经在申请撤销我的加拿大国籍了。拍摄食物、动作片、音乐,无论是什……不管有没有隐喻,皮克斯这部动画电影都值得一看暑假已经快结束了,这个暑期档依旧乏善可陈,个人觉得近期唯一比较值得一看的,是皮克斯出品的动画电影《夏日友晴天》。虽然故事比较低龄化,但轻松流畅、画面唯美绮丽,是一部合格的……高晓攀最新写真曝光帅气晓先生解锁国潮新方向星关系1月20日讯近日,相声演员高晓攀曝光一组时尚写真。身着棕色机车夹克,彩色格纹风衣以及的酷炫的墨镜等单品,搭配高晓攀硬朗帅气的五官展现出新潮前卫的一面。驼色潮流西服套装,混……彭冠英释黑白全新写真简约质感彰显雅绅星关系1月15日讯近日,演员彭冠英释出一组全新黑白质感写真。该套LOOK中,彭冠英身着黑色修身西装,内搭硬质纯白衬衣及波点领带,经典西装三件套简约稳重,不失格调。素有九头身之称……崔心心时尚写真释出棕色波点裙诠释复古轻时尚星关系12月31日讯青年演员崔心心时尚写真再释出,与之前不同的是,此次崔心心大胆挑战复古造型,将上世纪90年代的轻时尚趋势再次重现,竟透露出一种别样的韵味。图中,崔心心暗……王菲女儿治疗唇裂花了几百万,嘴已经修复,脸越来越奇怪通过标题大家也看到了,本文要讲的就是王菲和她女儿的事情,提到王菲许多人就会想到她的婚姻,王菲因为离过两次婚的缘故,所以落下了一个不负责任的名声。其实在如今这个社会而言,不仅仅是……叶祖新演过很多嬉闹的角色演茂则终于骗过了观众为了让观众忘掉差不多十年前那部经典的《步步惊心》和他演红的角色老十,叶祖新这些年尝试出演了很多不同类型的角色。《清平乐》里,观众不仅看不到丝毫老十的影子,很多人甚至没有认……其他应收款其他应付款看似万能?其实隐藏了不少风险很多财务人员有这样的一个习惯,一旦遇到讲不清、道不明的业务,统统核算计入其他应收款、其他应付款科目。这样处理真的可以的吗?其他应收款、其他应付款是万能的吗?今天我们……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网