apache mina 用 NIO 进行网络数据传输
NIO中要用到缓冲区——ByteBuffer
apache mina出于以下两点原因对ByteBuffer进行了封装
1、ByteBuffer长度固定,对变长数据的支持不好
2、对某些数据类型支持不是很好
用IoBuffer包装ByteBuffer,实现对ByteBuffer的改进,屏蔽ByteBuffer的不足
如何包装,实现如下:
IoBuffer类是一个粗像类,它的方法基本上和ByteBuffer类的方法类似。apache mina直接使用IoBuffer,也就是间接地使用ByteBuffer。
AbstractIoBuffer继承IoBuffer,这是一个粗像类,它相当于IoBuffer的实现模板,也就是说具体的IoBuffer只需要简单的继承这个类就行了,如SimpleBufferAllocator中的SimpleBuffer 。
private class SimpleBuffer extends AbstractIoBuffer {
........
}
AbstractIoBuffer弥补了ByteBuffer的两点不足,它可以动态的改变缓冲区的大小。
IoBufferAllocator,一个接口 ,用于把ByteBuffer 包装为 IoBuffer。IoBuffer只要使用此接口的任意实例对象,就能对现有的ByteBuffer进行包装,除了包装现成的ByteBuffer,也可新建一个ByteBuffer,然后包装成IoBuffer。
SimpleBufferAllocator是一个IoBufferAllocator的实现类,IoBuffer默认使用这个类型的实例对象进行包装工作。由SimpleBufferAllocator进行包装后,产出的IoBuffer对象的具体类型为SimpleBuffer
SimpleBufferAllocator代码如下:
public class SimpleBufferAllocator implements IoBufferAllocator {
public IoBuffer allocate(int capacity, boolean direct) {
return wrap(allocateNioBuffer(capacity, direct));
}
public ByteBuffer allocateNioBuffer(int capacity, boolean direct) {
ByteBuffer nioBuffer;
if (direct) {
nioBuffer = ByteBuffer.allocateDirect(capacity);
} else {
nioBuffer = ByteBuffer.allocate(capacity);
}
return nioBuffer;
}
public IoBuffer wrap(ByteBuffer nioBuffer) {
return new SimpleBuffer(nioBuffer);
}
public void dispose() {
// Do nothing
}
private class SimpleBuffer extends AbstractIoBuffer {
private ByteBuffer buf;
protected SimpleBuffer(ByteBuffer buf) {
super(SimpleBufferAllocator.this, buf.capacity());
this.buf = buf;
buf.order(ByteOrder.BIG_ENDIAN);
}
protected SimpleBuffer(SimpleBuffer parent, ByteBuffer buf) {
super(parent);
this.buf = buf;
}
@Override
public ByteBuffer buf() {
return buf;
}
@Override
protected void buf(ByteBuffer buf) {
this.buf = buf;
}
@Override
protected IoBuffer duplicate0() {
return new SimpleBuffer(this, this.buf.duplicate());
}
@Override
protected IoBuffer slice0() {
return new SimpleBuffer(this, this.buf.slice());
}
@Override
protected IoBuffer asReadOnlyBuffer0() {
return new SimpleBuffer(this, this.buf.asReadOnlyBuffer());
}
@Override
public byte[] array() {
return buf.array();
}
@Override
public int arrayOffset() {
return buf.arrayOffset();
}
@Override
public boolean hasArray() {
return buf.hasArray();
}
@Override
public void free() {
// Do nothing
}
}
}
CachedBufferAllocator也是IoBufferAllocator的实现类,由它包装后产出的IoBuffer对象的具体类型为CachedBuffer
总的来说,这个包装的实现有点绕口,但是作为模板模式和代理模式结合的使用案例,还是值得借鉴。
还有作为工具类,IoBuffer的allocate()都是静态方法,又相当于工厂方法模式。