前文中的EventLoop分析中,我们知道了每个EventLoop都有一个对应的Selector,用于关注注册在其上的Channel的各种读写事件。
当发生读写事件时,会交由Unsafe(本质上也是Channel的包装类)来处理,比如读事件
// 1.在NioEventLoop.run中,接收到读事件,直接调用unsafe来处理,如下2方法所示
unsafe.read();
// 2.AbstractNioByteChannel.read
@Override
public final void read() {
final ChannelConfig config = config();
if (shouldBreakReadReady(config)) {
clearReadPending();
return;
}
final ChannelPipeline pipeline = pipeline();
...
ByteBuf byteBuf = null;
boolean close = false;
try {
do {
byteBuf = allocHandle.allocate(allocator);
allocHandle.lastBytesRead(doReadBytes(byteBuf));
...
// 事件处理交由ChannelPipeline
pipeline.fireChannelRead(byteBuf);
byteBuf = null;
} while (allocHandle.continueReading());
所以,要知道读事件该如何处理,理解ChannelPipeline是非常有必要的。
所以本文先来将ChannelPipeline、ChannelHandlerContext、ChannelHandler之间的关系理清楚。
1.ChannelPipeline依照之前的惯例,不知道这个接口是做什么的,就先看注释
/**
* A list of {@link ChannelHandler}s which handles or intercepts inbound events and outbound operations of a
* {@link Channel}. {@link ChannelPipeline} implements an advanced form of the
* Intercepting Filter pattern
* to give a user full control over how an event is handled and how the {@link ChannelHandler}s in a pipeline
* interact with each other.
*
*/
public interface ChannelPipeline
extends ChannelInboundInvoker, ChannelOutboundInvoker, Iterable {
}
有几个重点:
ChannelPipeline是一组ChannelHandler的集合;
ChannelPipeline的实现是一种拦截过滤器模式;
用户可以自定义ChannelHandler来进行事件处理;
1.1 ChannelPipeline类结构图
笔者比较喜欢这种视图,干脆直接,可以较快找到接口的重要方法。
* ChannelPipeline接口主要提供的是对ChannelHandler的操作,增删(方法addLast、remove)等(毕竟之前说过ChannelPipeline是一组ChannelPipeline的集合);还有就是一系列的fire开头的方法(用于触发对各种读写注册类事件的响应),后续我们会仔细分析;
* 其父接口ChannelInboundInvoker,主要提供的是inbound(入事件,比如注册、可读事件等)的操作;
* 另一个父接口ChannelOutboundInvoker,主要提供的是outbound(出事件,比如连接远程服务、可写出事件等)的操作;
* Iterable就比较好理解了,就是用来循环获取内部类(ChannelHandler类)
1.2 ChannelPipeline默认实现与构造ChannelPipeline接口提供了默认实现类DefaultChannelPipeline,我们来看下其构造方法及主要属性
public class DefaultChannelPipeline implements ChannelPipeline {
// pipeline对应的头部和尾部Handler实现
final AbstractChannelHandlerContext head;
final AbstractChannelHandlerContext tail;
// pipeline所属的channel
private final Channel channel;
// 是否被注册
private boolean registered;
// 默认构造方法
protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true);
// 在这里构造了一个双向链表
tail = new TailContext(this);
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
}
从ChannelPipeline的基本属性和其默认构造方法中,我们了解到,ChannelPipeline属于某一个Channel;并且其构造了一个双向链表,tail和head互相指向;
但是这个TailContext和HeadContext到底是什么呢?我们先不纠结,继续往下看。
2.ChannelHandlerContext上述2中的TailContext和HeadContext本质上是ChannelHandlerContext接口的实现。
/**
* Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline}
* and other handlers.
**/
public interface ChannelHandlerContext extends AttributeMap, ChannelInboundInvoker, ChannelOutboundInvoker {
}
从注释中我们可以看出来,ChannelHandlerContext是一个关联接口,用于关联ChannelPipeline和其他ChannelHandler。
2.1 ChannelHandlerContext类结构
与ChannelPipeline类似,ChannelHandlerContext也继承了ChannelInboundInvoker和ChannelOutboundInvoker接口,这两个接口与之前分析ChannelPipeline时是一样的功能,也是用于inbound和outbound事件的处理;
不太一样的就是ChannelHandlerContext接口本身有对channel和ChannelHandler的依赖。
只看这些抽象的方法我们还看不出什么来,不用担心,带着疑问继续往下看。
2.2 ChannelHandlerContext默认实现与构造// DefaultChannelHandlerContext就是ChannelHandlerContext的默认实现
final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {
private final ChannelHandler handler;
// 在构造方法中传入ChannelPipeline和ChannelHandler等参数
DefaultChannelHandlerContext(
DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {
super(pipeline, executor, name, handler.getClass());
this.handler = handler;
}
@Override
public ChannelHandler handler() {
return handler;
}
}
// AbstractChannelHandlerContext构造实现
abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannelHandlerContext.class);
// 前一个和后一个ChannelHandlerContext节点
volatile AbstractChannelHandlerContext next;
volatile AbstractChannelHandlerContext prev;
// 关联的ChannelPipeline
private final DefaultChannelPipeline pipeline;
AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor,
String name, Class
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?