1.1 介绍

DataBuffer接口定义了在byte缓冲区上的抽象,引入它的原因是不是代替java.nio.ByteBuffer, 是由于Netty. Netty不使用ByteBuffer, 而是使用ByteBuf来代替. Spring的DataBuffer就是在ByteBuf上的简单抽象, 它也能用于非Netty平台.

1.2 DataBufferFactory

DataBufferFactory提供了分配新的数据缓冲区和包装现有数据的功能.allocate方法以一个默认的给定容器分配一个新的数据缓冲区. 虽然DataBuffer会按需扩大或收缩空间, 但是如果已知空间大小 ,则分配前给定空间大小是有好处的. wrap方法包装现有的ByteBuffer或byte数组, 包装不涉及分配, 它只是简单的用一个DataBuffer实现包装给定的数据.DataBufferFactory接口有两个实现:

  • NettyDataBufferFactory: 在Netty平台上使用.
  • DefaultDataBufferFactory: 在其他平台上使用.
1.3 DataBuffer接口

这个接口类似于ByteBuffer接口, 但是它提供了一些与Netty的ByteBuf类似的功能.它提供了独立的读写位置, 这与JDK的ByteBuffer不同(它对读和写仅提供一个位置以及一个用于在两个IO操作之间切换的flip()操作).

0 <= read position <= write position <= capacity
  • 1.

当从DataBuffer中读取字节时,读写的位置都会根据从缓冲区读写的数据量自动更新.在写数据时,DataBuffer的容量也会自动扩展,就如同StringBuilder, ArrayList一样.

另外, DataBuffer也提供了一些方法可以将其作为ByteBuffer, InputStream, 或OutputStream来进行操作.它还提供了确定给定byte位置的方法.
它也有两个实现:

  • NettyDataBuffer: 应用于Netty平台.
  • DefaultDataBuffer: 应用于其他平台.
1.3.1 PooledDataBuffer

PooledDataBuffer扩展了DataBuffer, 提供了应用计数的方法(池). retain方法将引用计数加1, release方法将引用计数减1, 当计数值为0时会释放缓冲内存空间.这两个方法都与引用计数有关.DataBufferUtils类提供了操作引用计数的实用方法, 它们都以一个DataBuffer实例作为参数, 但仅当参数为PooledDataBuffer类型时才会调用retailrelease方法.
通常, 访问DataBuffer的最后一个组件负责释放它, 在spring中,这有两个组件可以释放缓冲区, 即decoderstransports, decoder负责将缓冲区的流转换为其他类型, transport负责传输流(如HTTP消息), 如果你在分配数据缓冲区的过程中出现了异常, 此时你只能自己释放它.
示例:

DataBufferFactory factory = ...
// 分配一个新的缓冲区
DataBuffer buffer = factory.allocateBuffer();  
// 缓冲区是否应该被释放
boolean release = true; 
try {
    // 给缓冲区中写入数据, 它可能抛出异常, 所以要在finally中释放它.
    writeDataToBuffer(buffer); 
    putBufferInHttpBody(buffer);
// 如果没有发生异常, 当释放标志改为false,缓冲区将会作为通过网络发送的HTTP body的一部分被释放
    release = false; 
}
finally {
    if (release) {
        // 如果发生了异常,这个标志仍为true, 缓冲区将被释放.
        DataBufferUtils.release(buffer); 
    }
}

private void writeDataToBuffer(DataBuffer buffer) throws IOException { 
    ...
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
1.3.2 DataBufferUtils

DataBufferUtils包含了一些操作数据缓冲区的实用方法.参考相关文档.

Codecsorg.springframework.core.codec包提供了两个主要抽象, 用于byte流与对象流之间的相互转换.Encoder接口的功能是将对象流编码为数据缓冲区的输出流, Decoder与之相反, 它是将数据缓冲区的流转换为对象流. 注意decoder实例要考虑引用计数.
spring提供了大量的默认解编码器, 能够转换字符串, ByteBuffer, byte数组.
在spring的响应式框架中,解编码器还被用来将请求body转换为控制器参数, 或将返回类型转换到response body中返回给客户端.默认的解编码器在WebFluxConfigurationSuport类中配置, 也可以通过这个类的configureHttpMessageCodecs方法进行修改.