Spring框架中事件发布及其原理


在业务系统中,当多个模块之间需要进行通信的时候,事件可以作为信使传递消息,从而使模块之间免于耦合,因此利用事件机制十分常见。那么,在spring中如何发布一个事件,又如何监听并处理一个事件呢?

事件源发布事件

定义事件源

事件源通常是某个业务类,当它处理完自身的业务逻辑后,向外某个事件发布事件。

//业务类
public void produceData{
  ...
    springContextHolder.publishEvent(new DataEvent("数据产生了"))
  ...
}
定义事件

事件源中发布的事件DateEvent是一个继承了applicationEvent的自定义类

public class DataEvent extends ApplicationEvent{
  String field1;
  public DataEvent(String msg){
    super("DataEvent");
    this.field1=msg;
  }
  	....
}
定义监听器

事件、发布事件的事件源都定义好了,那么由谁来发出事件呢?DataEvent事件的监听器DataEventListener是一个实现了ApplicationListener的类,通过重写onApplicationEvent方法,可以实现监听器接收到相应事件后的处理逻辑。

为了简单起见,这里就直接输出dataEvent事件中携带的msg。

public class DataEventListener implements ApplicationListener<DataEvent>
{
   @Override
    public void onApplicationEvent(DataEvent dataEvent)
    {
     	//这里可以写自己的逻辑
      System.out.print(dataEvent.getField1());
    }
}
测试
//业务类执行produceData方法
produceData();
//控制台会输出
"数据产生了"

上述是一个spring发布事件的例子。

作为程序员不能只会用,不懂其中的原理。这样长久下去会让自己在职场上失去议价能力,在互联网行业是很危险的。

说个题外话吧,我记得之前有段时间公司的业务比较忙,于是就把一部分非核心工作交给了外包公司的人,外包的人员在我们公司驻场开发。所以和他们之间有一段比较密切的接触

一开始不太熟悉的时候,我内心替他们感到不公,觉得都是同行,都一样上下班,为啥他们待遇那么低(那时候年轻,圣母心泛滥)。但是时间一久,我就发现问题所在了。他们基本上有一个很普遍的问题,就是不求甚解。当他们拿到一个需求后,不会多问,不会深究。基本就是照着模板代码替换和修改,称之为“像素级”的模仿都不为过

由于不清楚其中的原理,所以经常会被一些小问题给卡住。不知道为什么,总是感觉他们很焦虑,被卡住就直接copy异常提示赶紧上百度搜,甚至不会自己去加工和提炼一下异常提示再去搜。大多数时候,逻辑问题是搜不出来的,然后他们会变得越来越焦躁,压力越来越大,最后查不到就束手无策

久而久之,个人自信心下降,更加没有心情和决心去探究一个问题。最后是啥结局,可能不用多说,我们都明白

不过凡事都有例外,当时那一批驻场员工中有一个小伙年龄不大,小时候在农村教育条件不好,后来上了个大专。毕业以后大公司卡学历,最后没办法才去的外包。但是,他和别人不太一样。他的决心和求知欲都明显超过那一批中的其他人。他遇到问题,也不会,有时候也焦虑,他也上网查。但是和别人不一样。他查过的东西,绝对不会再卡住他第二次。甚至查过一个问题,相似的问题也难不住他。他人并不聪明,就是有一股往里钻的劲儿支撑着他

我对他印象特别深刻,当时就觉得他和其他人那种应付交差的态度很不一样。果然,后来听同事说这个小伙有次去另外一个一线大厂驻场,被那个组的leader看中,最后留下来变成正式员工了

顺便给自己的公粽号打个广告吧,欢迎围观“趣论编程”。

好了,说了太多题外话。说回正题,我们探究一下spring为什么能够发布事件吧,探究一下它背后的机理是啥。

springContextHolder

从上边可以看出,springContextHolder.publishEvent向外推送了数据。springContextHolder是自己定义的类,它实现了ApplicationContextAware接口。

public class SpringContextHolder implements ApplicationContextAware {
  private ApplicationContext applicationContext;
  
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)throws BeansException {
        this.applicationContext=applicationContext;
    }

    public ApplicationContext getApplicationContext()
    {
        return  applicationContext;
    }
  
    /**
     * 发布事件
     * @param applicationEvent
     */
    public void publishEvent(ApplicationEvent applicationEvent)
    {
        applicationContext.publishEvent(applicationEvent);
    }
  
  	//这里省略无关代码
}

我们可以得出两点:

第一:springContextHolder继承了ApplicationContextAware接口。

第二:springContextHolder也不是真正发送事件的对象,而是委托了applicationContext发布事件。

那么我们分别来讨论下边两点。

1.springContextHolder为什么能拿到applicationContext,是什么时候被初始化的?

2.委托给applicationContext的事件又是如何被发布的?

ApplicationContextAware接口

Spring提供了大量的aware接口,spring的aware接口赋予bean获得spring容器服务的能力。

aware接口 作用
BeanNameAware 可以获取容器中bean的名称
BeanFactoryAware 获取当前bean factory这也可以调用容器的服务
MessageSourceAware 获得message source,这也可以获得文本信息
ResourceLoaderAware 获得资源加载器,可以获得外部资源文件的内容
applicationEventPulisherAware 应用事件发布器,可以发布事件
ApplicationCo
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值