netty之AttributeMap

这几天开始看netty,作些笔记。
netty5文档中 ChannelHandler开始处介绍了attachment的使用,用来保存handler的状态信息

public class DataServerHandler extends SimpleChannelInboundHandler<Message> {
   private final AttributeKey<Boolean> auth =
           new AttributeKey<Boolean>("auth");

   @Override
   public void channelRead(ChannelHandlerContext ctx, Integer integer) {
     Attribute<Boolean> attr = ctx.getAttr(auth);
     //...
 }

AttributeKey<T>和Attribute<T>应该就是map中的键值对,而这个map应该绑定在ChannelHandlerContext中。

文档中对ChannelHandlerContext的描述:
A ChannelHandler is provided with a ChannelHandlerContext object. A ChannelHandler is supposed to interact with the ChannelPipeline it belongs to via a context object. Using the context object, the ChannelHandler can pass events upstream or downstream, modify the pipeline dynamically, or store the information (attachment) which is specific to the handler.

一个handler有一个与之对应的context,handler通过这个context对象与pipeline互动,
使用这个上下文对象,可以实现...保存某个handler的信息(attachment)。

查看源码:
DefaultChannelHandlerContext继承了DefaultAttributeMap
final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext{...} 

DefaultAttributeMap的实现:
    @SuppressWarnings("rawtypes")
    private static final AtomicReferenceFieldUpdater<DefaultAttributeMap, Map> updater = AtomicReferenceFieldUpdater.newUpdater(DefaultAttributeMap.class, Map.class, "map");

    private volatile Map<AttributeKey<?>, Attribute<?>> map;

    @Override
    public <T> Attribute<T> attr(AttributeKey<T> key) {
        Map<AttributeKey<?>, Attribute<?>> map = this.map;
        if (map == null) {
            // Not using ConcurrentHashMap due to high memory consumption.
            //创建一个初始值为2的IdentityHashMap,控制内存消耗
            map = new IdentityHashMap<AttributeKey<?>, Attribute<?>>(2);
            if (!updater.compareAndSet(this, null, map)) {
                //如果原子更新失败,即执行到这里时map被其它线程赋值,而不是预期的              
                //null值,那就直接使用当前值                
                map = this.map;
            }
        }

        //同步块,如果获得的attribute<T>是null,那就创建一个DefaultAttribute<T>
        synchronized (map) {
            @SuppressWarnings("unchecked")
            Attribute<T> attr = (Attribute<T>) map.get(key);
            if (attr == null) {
                attr = new DefaultAttribute<T>(map, key);
                map.put(key, attr);
            }
            return attr;
        }
    }
    //......

可见作者在此处作了严密的控制,看到这里,心里充满了安全感

另外要注意的是:
因为在 ChannelHandlerContext 中的 AttibuteMap 是绑定在该上下文中的,所以你在某个上下文中定义的 Attribute 在另一个handler的上下文中是看不到的。
Channel 中也实现了 AttributeMap,你可以使用绑定在 Channel 中的 AttributeMap,用来在handler之间传递attachment。
ctx.channel().attr(...)...;   

你可能感兴趣的:(netty,AttributeMap)