2

居然可以这样监听,你学会了吗?

 1 year ago
source link: https://www.51cto.com/article/722776.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

​前面讲到要使自定义注解生效需要写一段驱动代码,那驱动代码什么开始执行比较合适呢?大家可能知道答案:应用启动的时候。

回到具体的代码实现中,假设应用程序(客户端或服务端)依赖了 RPC框架并且使用了Spring​环境,对Spring​比较熟悉的小伙伴应该知道,Spring​在启动的过程中会初始化bean​,那是不是可以在初始化bean之后去执行这段驱动代码呢?答案是肯定的。

查阅相关资料后,Spring 监听器可以实现上面这个诉求。

Spring 监听器

监听器在使用过程中可以监听某些感兴趣的事件,监听到事件来临时可以做出响应处理。

Spring事件监听体系包括三大核心组件:事件监听器、事件、事件广播器,如下图:

图片

Spring 监听器

事件广播器

事件广播器或者叫事件多播器负责广播发生的事件并通知所有监听器,所有的事件监听器都会提前注册在事件广播器中。

所有的动作都可能被定义为一个事件,事件发生后事件广播器通知所有的监听器,监听器根据情况做出响应。

Spring 定义了一个事件基类:ApplicationEvent,看一下源码:

public abstract class ApplicationEvent extends EventObject {
   /** 事件发生的时间 */
   private final long timestamp;

   /**
    * 创建一个实例
    * @param source 事件来源 
    */
   public ApplicationEvent(Object source){
      super(source);
      this.timestamp = System.currentTimeMillis();
   }
  ……省略其他代码
}

ApplicationEvent​ 继承 JDK 定义的事件基类:EventObject,

public class EventObject implements java.io.Serializable {
    /**
     * The object on which the Event initially occurred.
     */
    protected transient Object source;
  ……省略其他代码
}

ApplicationEvent 是一个抽象类,如果需要自定义事件需要继承这个类:

public class MyEvent extends ApplicationEvent {
  ……省略其他代码
}

当然 Spring 自身已经定义了非常多的事件:

  • ContextRefreshedEvent:ApplicationContext 被初始化或刷新时,该事件被发布。初始化是指所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用。
  • ContextStartedEvent:ApplicationContext 启动后,该事件被发布。
  • ContextStoppedEvent:ApplicationContext 停止后,该事件被发布。
  • ContextClosedEvent:ApplicationContext 关闭后,该事件被发布。

以上仅仅列举了几个常用的 Spring 事件。

根据前面分析的业务诉求,我们期望所有的bean​初始化完之后开始执行自定义注解的驱动代码,所以ContextRefreshedEvent这个事件才是我们感兴趣的,看一下源码:

public class ContextRefreshedEvent extends ApplicationContextEvent {
   public ContextRefreshedEvent(ApplicationContext source){
      super(source);
   }
}

看起来非常简单,继承了ApplicationContextEvent​,继续跟一下源码可以发现ApplicationContextEvent​继承了我们上面讲的ApplicationEvent。

事件监听器

所有的事件监听器都注册在事件广播器中,这好比观察者模式中的观察者。

在 Spring 中ApplicationListener​是事件监听器的顶层接口,继承自 JDK 的EventListener,所有的监听器都必须实现这个接口。

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
 /**
  * 处理事件
  * @param event 待响应的事件
  */
 void onApplicationEvent(E event);
  
  // ……省略其他代码
}

定义了一个onApplicationEvent方法,当有感兴趣的事件发生后就会执行这个方法进行处理。

实现自定义监听器

上面介绍了 Spring 监听体系的一些基础知识,并通过一些源码进行辅助介绍,这些代码都不是 RPC 框架要写的,RPC 框架当前要做的是实现一个自定义监听器监听感兴趣的事件。

通过结合业务诉求分析出:自定义一个监听器用来监听 Spring 内置ContextRefreshedEvent事件。

public class DefaultRpcListener implements ApplicationListener<ContextRefreshedEvent> {
    public DefaultRpcListener(){
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event){
        // TODO 实现业务逻辑
       // 1 服务端逻辑处理
       // 2 客户端逻辑处理
    }
}

自定义的监听器实现了ApplicationListener​接口,并重写onApplicationEvent方法,方法中待实现的业务逻辑是重中之重。

待实现的业务逻辑中需要对@ServiceExpose和@ServiceReference​这两个注解进行处理,@ServiceExpose​对应服务端,@ServiceReference对应客户端,所以基本就是两大块:服务端逻辑处理和客户端逻辑处理。

注意一下,文中提到的服务端或客户端是站在功能角度上看的,不能片面理解,一个应用程序(服务或微服务)既可能是服务端也可能是客户端:

图片

Spring 监听器-第 2 页

如上图,微服务 A 调用微服务 B,微服务 B 又调用微服务 C,微服务 B 在整个调用链中既是客户端又是服务端。

自定义监听器DefaultRpcListener放在 listener 包下,目前 RPC 框架代码工程结构如下:

├── easy-rpc-spring-boot-starter
    ├── pom.xml
    ├── src
    │   └── main
    │       ├── java
    │       │   └── com
    │       │       └── leixiaoshuai
    │       │           └── easyrpc
    │       │               ├── annotation
    │       │               │   ├── ServiceExpose.java
    │       │               │   └── ServiceReference.java
    │       │               └── listener
    │       │                   └── DefaultRpcListener.java
    │       └── resources
    └── target

本小节首先学习了Spring 监听的基本机制,了解到监听体系有三大关键要素:事件监听器、事件、事件广播器,事件监听器会提前注册到事件广播器中,当感兴趣的事件发生后事件广播器会通知到事件监听器,这样事件监听器就可以根据业务场景进行响应。

Spring 提供了事件的基类,大家可以自定义事件,当然也可以直接使用 Spring 内置的事件,结合 RPC 框架的业务特点我们发现ContextRefreshedEvent事件比较符合我们的诉求。

Spring 定义了事件监听器ApplicationListener​顶层接口,我们只需要实现该接口就可以自定义一个监听器,在监听器中重写onApplicationEvent方法实现相应的业务逻辑。

自定义监听器主要的业务逻辑包括两大块:服务端和客户端,服务端逻辑主要处理@ServiceExpose​注解,客户端逻辑主要处理@ServiceReferece注解。关于注解处理的逻辑我们下一小节详细讲解。


Recommend

  • 10

    三个Windows的小窍门,你学会了吗?发布于 01-09 · 2283 次播放视频相关好物知乎盐选会员¥19.00 起

  • 6

    大家好,我是安果!在编写爬虫前,我们都需要对目标应用进行抓包,然后分析一波后,才能进入到编写脚本的阶段对于使用 iPhone 的小伙伴来说,日常抓包不要太容易。PC 端工具,比如:Charles、Fiddler 完全够打;「 Stream」是 iOS 端一款非常强大...

  • 4

    五分钟学会 gRPC,你学会了吗?-51CTO.COM 五分钟学会 gRPC,你学会了吗? 作者:crossoverJie 2022-03-08 08:39:22 gRPC 内容还是非常多的,本文只是作为一份入门资料希望能让不了解 gRPC 的能...

  • 2

    小包第一个 qq 号前面是 444 ,用久了,感觉看 4 这个数字真顺眼。恰逢 Promise 也有四个很像的静态三兄弟(Promise.all、Promise.allSettled、Promise.race、Promi...

  • 4

    小包第一个 qq 号前面是 444 ,用久了,感觉看 4 这个数字真顺眼。...

  • 7

    一、bq24735简介bq24735 是一款高效率同步电池充电器。当系统供电需求暂时高于适配器最大供电水平的时候, bq24735 使用智能加速技术来允许电池向系统中释放能量,这样的话将保护适配器不被损坏。

  • 5

    云上数据安全优秀实践,你学会了吗?-51CTO.COM 云上数据安全优秀实践,你学会了吗? 作者:肖力 翻译 2022-04-22 08:10:45 HSM 是设计有物理安全方面和符合政府法规的软件安全工具的硬件。物理...

  • 5

    ​一、云上应用现状与挑战G行为深化“123+N”数字化发展体系,建设自主可控的全栈云平台,全面支持云原生、微服务和分布式等技术。然而由于在全栈云环境中因容器漂移、自动扩缩容使得应用故障现场难以还原,同时微服务技术的应用也使得...

  • 3

    Pandas Query 方法深度总结,你学会了吗?-51CTO.COM Pandas Query 方法深度总结,你学会了吗? 作者:周萝卜 2022-07-26 00:25:57 事实证明实际上可以使用 query()​ 方法做到这一点...

  • 3

    Kubernetes 节点磁盘故障排查,你学会了吗?-51CTO.COM Kubernetes 节点磁盘故障排查,你学会了吗? 作者:祝祥 2022-07-26 08:03:27 在Kubernetes 环境中,随着时间的推移,这可能...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK