我们在讨论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(); } }