【netty-socketio】@OnEvent作用

下面主要讲解跟 @OnEvent 相关代码的注释

一:SocketIoServer创建

启动服务端,首先要创建SocketIoServer,创建socketIoServer实例时做了如下几件事:

  1. 创建namespacesHub = new NamespacesHub(读取到的配置#{com.corundumstudio.socketio}),存放创建的所有的Namespace
  2. 创建并添加默认mainNamespace<“”,mainNamespace>到namespacesHub.namespaces中,mainNamespace默认名为空“”
  3. 创建mainNamespace时创建了ScannerEngine engine = new ScannerEngine() ,主要负责找到注解对应的AnnotationScanner
  4. 创建engine时创建了3个AnnotationScanner并放到了全局变量 annotations 中,用于定义扫描哪些注解,以及扫描到这些注解后要添加哪些监听,及调用到被这些注解标注的方法时要做的事情
private static final List<? extends AnnotationScanner> annotations=
 Arrays.asList(new OnConnectScanner(), new OnDisconnectScanner(), new OnEventScanner());

二:SpringAnnotationScanner 注解扫描器

其实SpringAnnotationScanner实现了BeanPostProcessor,定义了三个要处理的注解

private final List<Class<? extends Annotation>> annotations =
      Arrays.asList(OnConnect.class, OnDisconnect.class, OnEvent.class);
  1. 前置处理器: 判断要创建的bean中的方法是否有annotations 中定义的注解,有则赋值此类给originalBeanClass
  2. 后置处理器: 判断originalBeanClass是否为null,不为null,说明此类在前置处理器中判断此类中有方法有annotations中的注解 ,则
    a. 向上面创建的socketIoServer实例中添加监听:socketIOServer.addListeners(bean, originalBeanClass);
    b. 将originalBeanClass置为null

三:SocketIoServer

  1. socketIdServer.addListeners(Object listeners, Class<?> listenersClass) 添加注解对应的监听

    a. 调用mainNamespace.addListeners(listeners, listenersClass),啥也没做,直接调用scannerEngine.scan
    b. 调用scannerEngine.scan(Namespace namespace, Object object, Class<?> clazz)
      I. 获取此类中声明的方法,若这些方法标有annotations中对应的注解,则调用该注解对应的注解扫描器AnnotationScanner的下面两个方法,
      II. annotationScanner.validate:校验方法入参进行校验,如OnEventScanner.validate
      III. annotationScanner.addListener:向对应的注解扫面器annotationScanner添加监听,如OnEventScanner.addListener,当该注解标注的方法被调用时,就会回调添加监听者的onData方法进行对应的逻辑处理

四:OnEventScanner

  1. validate(Method method, Class<?> clazz):参数个数校验
    a. 获取方法参数列表参数个数paramsCount
    b. 获取方法中SocketIOClient和AckRequest类型的参数在参数列表中的个数socketIOClientIndex
    c. 获取方法中AckRequest类型的参数在参数列表中的个数ackRequestIndex
    d. 获取方法中除SocketIOClient和AckRequest类型所有真正业务用来传输数据的所有参数在参数列表中个数dataIndexes.size()
    e. 判断paramsCount是否等于socketIOClientIndex+ackRequestIndex+dataIndexes.size()
  2. addListener(Namespace namespace, final Object object, final Method method, Annotation annot)
    a. 调用namesapce.addEventListener(eventName, eventClass, listener)

五:Namespace

private final ScannerEngine engine = new ScannerEngine();
private final ConcurrentMap<String, EventEntry<?>> eventListeners = PlatformDependent.newConcurrentHashMap();

  1. addListeners(Object listeners, Class<?> listenersClass)
    a. 只调用了下engine.scan(this, listeners, listenersClass);
  2. addMultiTypeEventListener(String eventName, MultiTypeEventListener listener,
    Class<?>… eventClass)真正给事件添加了监听者

    a. 创建EventEntry<“#{方法@OnEvent对应的value},entry”>并存入eventListeners
    b. 向entry添加监听者DataListener类型的OnEventScanner,实现onData方法,方法作用:
      I. 获取方法所有参数存入args
      II. 通过反射真正执行被注解标注的方法method.invoke(object, args)

六: EventEntry

private final Queue<DataListener<T>> listeners = new ConcurrentLinkedQueue<DataListener<T>>();;
  1. addListener(DataListener listener):将DataListener监听保存到listeners

以上都是启动Bean出事后完成的工作,下面就是建立连接后通过channel传输数据时的逻辑了


当前端发送数据到channel时,最终会走到pipeline中的InPacketHandler节点,从而走到channelRead0,从而调用 PacketListener.onPacket(Packet packet, NamespaceClient client, Transport transport) ,若type=Message;subType=PacketType.ACK,接着调用Namespace.onEvent(NamespaceClient client, String eventName, List<Object> args, AckRequest ackRequest),下面着重看一下Namespace.onEvent做了哪些事情:

七: Namespace.onEvent(NamespaceClient client, String eventName, List args, AckRequest ackRequest)

  1. 首先根据eventName获取eventListeners中对应的EntryEntry从而获取对应的所有监听DataListener
  2. 回调所有监听的onData,执行真正的监听逻辑,在onData里面通过反射调用了真正的方法

整体流程

在这里插入图片描述

大致逻辑: 服务端启动初始化bean时,利用SpringAnnotationScanner 的前后置处理器,找到@OnEvent注解,并将其key为@OnEvent设置的value,value为监听包装成的EventEntry保存到Namespace的eventListeners中 private final ConcurrentMap<String, EventEntry<?>> eventListeners = PlatformDependent.newConcurrentHashMap()中,当有数据写入cannel中,服务端在读取channel中的数据时,获取对应namespace的所有监听eventListeners,并找到key为指定事件名的所有监听,并调用监听的onData方法,onData作为对应的逻辑处理后通过反射调用注解锁标注的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值