Netty中ChannelOption与ConstantPool

我们在讨论Netty的服务器启动程序的bind()方法源码时,看到有这样的一段代码:

    void init(Channel channel) throws Exception {
        final Map<ChannelOption<?>, Object> options = options0();
        synchronized (options) {
            setChannelOptions(channel, options, logger);
        }

这段代码的作用就是获取辅助类ServerBootstrap中的options属性,并且遍历调用setChannelOptions()

    static void setChannelOptions(
            Channel channel, Map<ChannelOption<?>, Object> options, InternalLogger logger) {
        for (Map.Entry<ChannelOption<?>, Object> e: options.entrySet()) {
            setChannelOption(channel, e.getKey(), e.getValue(), logger);
        }
    }
    @SuppressWarnings("unchecked")
    private static void setChannelOption(
            Channel channel, ChannelOption<?> option, Object value, InternalLogger logger) {
        try {
             //从这个地方我们可以看出,这是对channel本身的config进行设置。
             if (!channel.config().setOption((ChannelOption<Object>) option, value)) {
                logger.warn("Unknown channel option '{}' for channel '{}'", option, channel);
            }
        } catch (Throwable t) {
            logger.warn(
                    "Failed to set channel option '{}' with value '{}' for channel '{}'", option, value, channel, t);
        }
    }

我们讨论一下ChannelOption类本身的结构是什么样子的:

package io.netty.channel;

import io.netty.buffer.ByteBufAllocator;
import io.netty.util.AbstractConstant;
import io.netty.util.ConstantPool;

import java.net.InetAddress;
import java.net.NetworkInterface;

/**
 * A {@link ChannelOption} allows to configure a {@link ChannelConfig} in a type-safe
 * way. Which {@link ChannelOption} is supported depends on the actual implementation
 * of {@link ChannelConfig} and may depend on the nature of the transport it belongs
 * to.
 * ChannelOption 允许以一种类型安全的方式去配置ChannelConfig.支持哪种ChannelOption取决于ChannelConfig的具体实现,
 * 以及它所属的传输的性质(说白可能就是什么样的传输方式会有什么样的ChannelOption)
 * 可以看出来,ChannelOption 提供了大量的静态方法供我们调用。ChannelOption做为key使用一般,不维护值,提供了大量的默认的选项。
 * @param <T>   the type of the value which is valid for the {@link ChannelOption}
 * 参数中的T是泛型,他是value的类型
 */
public class ChannelOption<T> extends AbstractConstant<ChannelOption<T>> {

	//提供一个私有的静态成员变量ConstantPool(常量池),用来获取特定名称的ChannelOption值。
    private static final ConstantPool<ChannelOption<Object>> pool = new ConstantPool<ChannelOption<Object>>() {
        @Override
        protected ChannelOption<Object> newConstant(int id, String name) {
            return new ChannelOption<Object>(id, name);
        }
    };

    /**
     * Returns the {@link ChannelOption} of the specified name.
     * 返回特定名称的ChannelOption,可以看出,调用了常量池的方法,下面我们对常量池做一个介绍
     */
    @SuppressWarnings("unchecked")
    public static <T> ChannelOption<T> valueOf(String name) {
        return (ChannelOption<T>) pool.valueOf(name);
    }
    /**
     * 省略
     */

    /**
     * Returns {@code true} if a {@link ChannelOption} exists for the given {@code name}.
     * 判断常量池中是否存在给定名称的值
     */
    public static boolean exists(String name) {
        return pool.exists(name);
    }

    /**
     * Creates a new {@link ChannelOption} for the given {@code name} or fail with an
     * {@link IllegalArgumentException} if a {@link ChannelOption} for the given {@code name} exists.
     * 使用给定的名字创建一个新的ChannelOption,如果已经存在则抛出异常
     * 
     */
    @SuppressWarnings("unchecked")
    public static <T> ChannelOption<T> newInstance(String name) {
        return (ChannelOption<T>) pool.newInstance(name);
    }

    //通过名称获取Allocator的ChannelOption。
    public static final ChannelOption<ByteBufAllocator> ALLOCATOR = valueOf("ALLOCATOR");
    /**
     * 省略
     */

    /**
     * Creates a new {@link ChannelOption} with the specified unique {@code name}.
     */
    private ChannelOption(int id, String name) {
        super(id, name);
    }

}

常量池ConstantPool

package io.netty.util;

import io.netty.util.internal.ObjectUtil;
import io.netty.util.internal.PlatformDependent;

import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * A pool of {@link Constant}s.
 * 常量池
 * @param <T> the type of the constant
 */
public abstract class ConstantPool<T extends Constant<T>> {

	//ConcurrentMap提供了原子性的方法,为线程安全。
    private final ConcurrentMap<String, T> constants = PlatformDependent.newConcurrentHashMap();

    //原子性的递增类。
    private final AtomicInteger nextId = new AtomicInteger(1);


    /**
     * Returns the {@link Constant} which is assigned to the specified {@code name}.
     * If there's no such {@link Constant}, a new one will be created and returned.
     * Once created, the subsequent calls with the same {@code name} will always return the previously created one
     * (i.e. singleton.)
     * 返回已经分配好了一个特定名称的常量
     * 如果常量池中不存在这个常量,则创建一个新的,并且返回
     * 一旦创建了,后续使用相同名称的调用总会返回之前创建的那个(单例)
     * @param name the name of the {@link Constant}
     */
    public T valueOf(String name) {
        checkNotNullAndNotEmpty(name);
        return getOrCreate(name);
    }

    /**
     * Get existing constant by name or creates new one if not exists. Threadsafe
     * 通过名称获取已经存在的常量,或者如果不存在,创建一个新的.这是一个线程安全的方法。
     * 为什么会线程安全?首先他使用了ConcurrentMap类,他提供了一些原子性的操作方法,比如在这个方法中使用的putIfAbsent,
     * 如果key 不存在,则返回null,存在则返回之前的值。
     * 第二:他使用了双重判定的方法,保证了两个线程同时进入第一个判断后,其中的某一个线程执行了更新操作,(这个更新操作是原子的),另一个线程执行更新操作会得到第一个线程产生的ChannelOption.
     * 
     * @param name the name of the {@link Constant}
     */
    private T getOrCreate(String name) {
        T constant = constants.get(name);
        if (constant == null) {
            final T tempConstant = newConstant(nextId(), name);
            constant = constants.putIfAbsent(name, tempConstant);
            if (constant == null) {
                return tempConstant;
            }
        }

        return constant;
    }
    /**
     * 使用id,name创建一个新的ChannelOption.
     * @param id
     * @param name
     * @return
     */
    protected abstract T newConstant(int id, String name);

    @Deprecated
    public final int nextId() {
        return nextId.getAndIncrement();
    }
}

猜你喜欢

转载自blog.csdn.net/u013828625/article/details/79802647