dubbo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] lkj41110 closed pull request #1577: a
Date Tue, 10 Apr 2018 05:08:54 GMT
lkj41110 closed pull request #1577: a
URL: https://github.com/apache/incubator-dubbo/pull/1577
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java
index db787747f5..fb4b1341a7 100644
--- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java
+++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java
@@ -36,6 +36,7 @@
 /**
  * Abstract implementation of Directory: Invoker list returned from this Directory's list method have been filtered by Routers
  *
+ * Directory 抽象实现类, TODO 芋艿,优化注释 增加router的Directory
  */
 public abstract class AbstractDirectory<T> implements Directory<T> {
 
diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/StaticDirectory.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/StaticDirectory.java
index a8563b643c..59425337af 100644
--- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/StaticDirectory.java
+++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/StaticDirectory.java
@@ -27,6 +27,7 @@
 /**
  * StaticDirectory
  *
+ * 静态 Directory 实现类
  */
 public class StaticDirectory<T> extends AbstractDirectory<T> {
 
@@ -80,7 +81,6 @@ public void destroy() {
 
     @Override
     protected List<Invoker<T>> doList(Invocation invocation) throws RpcException {
-
         return invokers;
     }
 
diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/AbstractClusterInvoker.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
index bf32bc723d..6e3a1259ff 100644
--- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
@@ -41,8 +41,8 @@
  */
 public abstract class AbstractClusterInvoker<T> implements Invoker<T> {
 
-    private static final Logger logger = LoggerFactory
-            .getLogger(AbstractClusterInvoker.class);
+    private static final Logger logger = LoggerFactory.getLogger(AbstractClusterInvoker.class);
+
     protected final Directory<T> directory;
 
     protected final boolean availablecheck;
@@ -233,7 +233,6 @@ public Result invoke(final Invocation invocation) throws RpcException {
     }
 
     protected void checkWhetherDestroyed() {
-
         if (destroyed.get()) {
             throw new RpcException("Rpc cluster invoker for " + getInterface() + " on consumer " + NetUtils.getLocalHost()
                     + " use dubbo version " + Version.getVersion()
diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/AvailableCluster.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/AvailableCluster.java
index 7c6c5f44b7..eb659f6f86 100644
--- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/AvailableCluster.java
+++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/AvailableCluster.java
@@ -35,7 +35,7 @@
     public static final String NAME = "available";
 
     public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
-
+        //
         return new AbstractClusterInvoker<T>(directory) {
             public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
                 for (Invoker<T> invoker : invokers) {
@@ -46,7 +46,6 @@ public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBal
                 throw new RpcException("No provider available in " + invokers);
             }
         };
-
     }
 
 }
\ No newline at end of file
diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
index 0a038c7433..1381af89e8 100644
--- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
@@ -62,7 +62,7 @@ public void destroy() {
     }
 
     public Result invoke(Invocation invocation) throws RpcException {
-        Result result = null;
+        Result result;
 
         String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
         if (value.length() == 0 || value.equalsIgnoreCase("false")) {
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java
index 0266c66256..ba5324e8e1 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java
@@ -37,6 +37,15 @@
 
     public static final String UNSUBSCRIBE = "unsubscribe";
 
+    /**
+     * 分类
+     *
+     * 目前有
+     * 1. {@link #PROVIDERS_CATEGORY} 服务提供者
+     * 2. {@link #CONSUMERS_CATEGORY} 服务消费者
+     * 3. {@link #ROUTERS_CATEGORY} 路由规则 http://dubbo.io/books/dubbo-user-book/demos/routing-rule.html
+     * 3. {@link #CONFIGURATORS_CATEGORY} 配置规则 http://dubbo.io/books/dubbo-user-book/demos/config-rule.html
+     */
     public static final String CATEGORY_KEY = "category";
 
     public static final String PROVIDERS_CATEGORY = "providers";
@@ -57,6 +66,13 @@
 
     public static final String CACHE_KEY = "cache";
 
+    /**
+     * `url.parameters.dynamic`
+     *
+     * 是否动态数据
+     *
+     * 若为 false ,该数据为持久数据,当注册方退出时,数据依然保存在注册中心。
+     */
     public static final String DYNAMIC_KEY = "dynamic";
 
     public static final String DUBBO_PROPERTIES_KEY = "dubbo.properties.file";
@@ -179,6 +195,7 @@
 
     public static final String DEPRECATED_KEY = "deprecated";
 
+    // TODO 【芋艿】anyhost 是什么
     public static final String ANYHOST_KEY = "anyhost";
 
     public static final String ANYHOST_VALUE = "0.0.0.0";
@@ -255,8 +272,13 @@
 
     public static final String RETRIES_KEY = "retries";
 
+    /**
+     * Telnet 提示键
+     */
     public static final String PROMPT_KEY = "prompt";
-
+    /**
+     * Telnet 提示值【默认】
+     */
     public static final String DEFAULT_PROMPT = "dubbo>";
 
     public static final String CODEC_KEY = "codec";
@@ -354,6 +376,9 @@
     public static final Pattern COMMA_SPLIT_PATTERN = Pattern
             .compile("\\s*[,]+\\s*");
 
+    /**
+     * 路径分隔符
+     */
     public final static String PATH_SEPARATOR = "/";
 
     public static final String REGISTRY_SEPARATOR = "|";
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Node.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Node.java
index c3cfef2949..72d83b1d78 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Node.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Node.java
@@ -18,12 +18,16 @@
 
 /**
  * Node. (API/SPI, Prototype, ThreadSafe)
+ *
+ * 节点
  */
 public interface Node {
 
     /**
      * get url.
      *
+     * 获得 URL
+     *
      * @return url.
      */
     URL getUrl();
@@ -31,11 +35,15 @@
     /**
      * is available.
      *
+     * 是否可用
+     *
      * @return available.
      */
     boolean isAvailable();
 
     /**
+     * 销毁
+     *
      * destroy.
      */
     void destroy();
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Resetable.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Resetable.java
index 81294e41eb..131d599bc8 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Resetable.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Resetable.java
@@ -18,13 +18,17 @@
 
 /**
  * Resetable.
+ *
+ * 可重置接口
  */
 public interface Resetable {
 
     /**
      * reset.
      *
-     * @param url
+     * 重置
+     *
+     * @param url URL
      */
     void reset(URL url);
 
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/URL.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/URL.java
index eb5c144b0d..c383d88b10 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/URL.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/URL.java
@@ -65,6 +65,10 @@
  * for this case, url protocol = null, url host = home, url path = user1/router.js
  * </ul>
  *
+ * 格式:protocol://username:password@host:port/path?key=value&key=value
+ * 所有配置最终都将转换为 URL 表示,并由服务提供方生成,经注册中心传递给消费方,各属性对应 URL 的参数,参见配置项一览表中的 "对应URL参数" 列。
+ * 来自 <a href="https://dubbo.gitbooks.io/dubbo-user-book/references/xml/introduction.html">schema 配置参考手册</>
+ *
  * @see java.net.URL
  * @see java.net.URI
  */
@@ -72,20 +76,36 @@
 
     private static final long serialVersionUID = -1985165475234910535L;
 
+    /**
+     * 协议名
+     */
     private final String protocol;
-
+    /**
+     * 用户名
+     */
     private final String username;
-
+    /**
+     * 密码
+     */
     private final String password;
 
-    // by default, host to registry
+    /**
+     * by default, host to registry
+     * 地址
+     */
     private final String host;
-
-    // by default, port to registry
+    /**
+     * by default, port to registry
+     * 端口
+     */
     private final int port;
-
+    /**
+     * 路径(服务名)
+     */
     private final String path;
-
+    /**
+     * 参数集合
+     */
     private final Map<String, String> parameters;
 
     // ==== cache ====
@@ -1208,6 +1228,14 @@ public InetSocketAddress toInetSocketAddress() {
         return new InetSocketAddress(host, port);
     }
 
+    /**
+     * 获得 Service 键
+     *
+     * 格式为 格式为 ${group}/${interface}:${version}
+     * 和 {@link StringUtils#getServiceKey(Map)} 一致
+     *
+     * @return 键
+     */
     public String getServiceKey() {
         String inf = getServiceInterface();
         if (inf == null) return null;
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Version.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Version.java
index 97e3a2173d..6eb524464f 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Version.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Version.java
@@ -56,6 +56,13 @@ private static boolean hasResource(String path) {
         }
     }
 
+    /**
+     * 获得类对应的版本号
+     *
+     * @param cls 类
+     * @param defaultVersion 默认版本号
+     * @return 版本号
+     */
     public static String getVersion(Class<?> cls, String defaultVersion) {
         try {
             // find version info from MANIFEST.MF first
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/ClassGenerator.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/ClassGenerator.java
index fdca662575..90fcec684c 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/ClassGenerator.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/ClassGenerator.java
@@ -45,18 +45,55 @@
 
 /**
  * ClassGenerator
+ *
+ * 类生成器,基于 Javassist 实现。
  */
 public final class ClassGenerator {
+
     private static final AtomicLong CLASS_NAME_COUNTER = new AtomicLong(0);
     private static final String SIMPLE_NAME_TAG = "<init>";
     private static final Map<ClassLoader, ClassPool> POOL_MAP = new ConcurrentHashMap<ClassLoader, ClassPool>(); //ClassLoader - ClassPool
+
+    /**
+     * CtClass hash 集合
+     * key:类名
+     */
     private ClassPool mPool;
+    /**
+     * CtClass 对象
+     *
+     * 使用 {@link #mPool} 生成
+     */
     private CtClass mCtc;
-    private String mClassName, mSuperClass;
+    /**
+     * 生成类的类名
+     */
+    private String mClassName;
+    /**
+     * 生成类的父类
+     */
+    private String mSuperClass;
+    /**
+     * 生成类的接口集合
+     */
     private Set<String> mInterfaces;
-    private List<String> mFields, mConstructors, mMethods;
+    /**
+     * 生成类的属性集合
+     */
+    private List<String> mFields;
+    /**
+     * 生成类的非空构造方法代码集合
+     */
+    private List<String> mConstructors;
+    /**
+     * 生成类的方法代码集合
+     */
+    private List<String> mMethods;
     private Map<String, Method> mCopyMethods; // <method desc,method instance>
     private Map<String, Constructor<?>> mCopyConstructors; // <constructor desc,constructor instance>
+    /**
+     * 默认空构造方法
+     */
     private boolean mDefaultConstructor = false;
 
     private ClassGenerator() {
@@ -211,6 +248,7 @@ public ClassGenerator addConstructor(int mod, Class<?>[] pts, String body) {
     }
 
     public ClassGenerator addConstructor(int mod, Class<?>[] pts, Class<?>[] ets, String body) {
+        // 构造方法代码
         StringBuilder sb = new StringBuilder();
         sb.append(modifier(mod)).append(' ').append(SIMPLE_NAME_TAG);
         sb.append('(');
@@ -230,6 +268,7 @@ public ClassGenerator addConstructor(int mod, Class<?>[] pts, Class<?>[] ets, St
             }
         }
         sb.append('{').append(body).append('}');
+        //
         return addConstructor(sb.toString());
     }
 
@@ -256,22 +295,30 @@ public ClassPool getClassPool() {
     }
 
     public Class<?> toClass(ClassLoader loader, ProtectionDomain pd) {
+        // mCtc 非空时,进行释放;下面会进行创建 mCtc
         if (mCtc != null)
             mCtc.detach();
         long id = CLASS_NAME_COUNTER.getAndIncrement();
         try {
             CtClass ctcs = mSuperClass == null ? null : mPool.get(mSuperClass);
+            // 类名
             if (mClassName == null)
                 mClassName = (mSuperClass == null || javassist.Modifier.isPublic(ctcs.getModifiers())
                         ? ClassGenerator.class.getName() : mSuperClass + "$sc") + id;
+            // 创建 mCtc
             mCtc = mPool.makeClass(mClassName);
+            // 继承类
             if (mSuperClass != null)
                 mCtc.setSuperclass(ctcs);
+            // add dynamic class tag.
             mCtc.addInterface(mPool.get(DC.class.getName())); // add dynamic class tag.
+            // 实现接口集合
             if (mInterfaces != null)
                 for (String cl : mInterfaces) mCtc.addInterface(mPool.get(cl));
+            // 属性集合
             if (mFields != null)
                 for (String code : mFields) mCtc.addField(CtField.make(code, mCtc));
+            // 方法集合
             if (mMethods != null) {
                 for (String code : mMethods) {
                     if (code.charAt(0) == ':')
@@ -280,8 +327,10 @@ public ClassPool getClassPool() {
                         mCtc.addMethod(CtNewMethod.make(code, mCtc));
                 }
             }
+            // 空参数构造方法
             if (mDefaultConstructor)
                 mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc));
+            // 带参数构造方法
             if (mConstructors != null) {
                 for (String code : mConstructors) {
                     if (code.charAt(0) == ':') {
@@ -292,6 +341,9 @@ public ClassPool getClassPool() {
                     }
                 }
             }
+//            mCtc.debugWriteFile("/Users/yunai/test/" + mCtc.getSimpleName().replaceAll(".", "/") + ".class");
+            mCtc.debugWriteFile("/Users/yunai/test/" + mCtc.getSimpleName() + ".class");
+            // 生成
             return mCtc.toClass(loader, pd);
         } catch (RuntimeException e) {
             throw e;
@@ -302,6 +354,9 @@ public ClassPool getClassPool() {
         }
     }
 
+    /**
+     * 释放
+     */
     public void release() {
         if (mCtc != null) mCtc.detach();
         if (mInterfaces != null) mInterfaces.clear();
@@ -324,6 +379,9 @@ private CtConstructor getCtConstructor(Constructor<?> c) throws NotFoundExceptio
         return getCtClass(c.getDeclaringClass()).getConstructor(ReflectUtils.getDesc(c));
     }
 
+    /**
+     * 动态编译接口,用于标记类是通过 {@link #ClassGenerator} 生成的
+     */
     public static interface DC {
     } // dynamic class tag interface.
 }
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Proxy.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Proxy.java
index f6761f715f..1b1d40c9c2 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Proxy.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Proxy.java
@@ -36,8 +36,8 @@
 /**
  * Proxy.
  */
-
 public abstract class Proxy {
+
     public static final InvocationHandler RETURN_NULL_INVOKER = new InvocationHandler() {
         public Object invoke(Object proxy, Method method, Object[] args) {
             return null;
@@ -48,8 +48,20 @@ public Object invoke(Object proxy, Method method, Object[] args) {
             throw new UnsupportedOperationException("Method [" + ReflectUtils.getName(method) + "] unimplemented.");
         }
     };
+    /**
+     * Proxy Class 计数,用于生成 Proxy 类名自增。
+     */
     private static final AtomicLong PROXY_CLASS_COUNTER = new AtomicLong(0);
+    /**
+     * 包名
+     */
     private static final String PACKAGE_NAME = Proxy.class.getPackage().getName();
+    /**
+     * Proxy 对象缓存
+     * key :ClassLoader
+     * value.key :Proxy 标识。使用 Proxy 实现接口名拼接
+     * value.value :Proxy 对象
+     */
     private static final Map<ClassLoader, Map<String, Object>> ProxyCacheMap = new WeakHashMap<ClassLoader, Map<String, Object>>();
 
     private static final Object PendingGenerationMarker = new Object();
@@ -75,22 +87,26 @@ public static Proxy getProxy(Class<?>... ics) {
      * @return Proxy instance.
      */
     public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
+        // 校验接口超过上限
         if (ics.length > 65535)
             throw new IllegalArgumentException("interface limit exceeded");
 
+        // use interface class name list as key.
         StringBuilder sb = new StringBuilder();
         for (int i = 0; i < ics.length; i++) {
             String itf = ics[i].getName();
+            // 校验是否为接口
             if (!ics[i].isInterface())
                 throw new RuntimeException(itf + " is not a interface.");
 
+            // 加载接口类
             Class<?> tmp = null;
             try {
                 tmp = Class.forName(itf, false, cl);
             } catch (ClassNotFoundException e) {
             }
 
-            if (tmp != ics[i])
+            if (tmp != ics[i]) // 加载接口类失败
                 throw new IllegalArgumentException(ics[i] + " is not visible from class loader");
 
             sb.append(itf).append(';');
@@ -109,16 +125,18 @@ public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
             }
         }
 
+        // 获得 Proxy
         Proxy proxy = null;
         synchronized (cache) {
             do {
+                // 从缓存中获取 Proxy
                 Object value = cache.get(key);
                 if (value instanceof Reference<?>) {
                     proxy = (Proxy) ((Reference<?>) value).get();
                     if (proxy != null)
                         return proxy;
                 }
-
+                // 缓存中不存在,设置生成 Proxy 代码标记。创建中时,其他创建请求等待,避免并发。
                 if (value == PendingGenerationMarker) {
                     try {
                         cache.wait();
@@ -134,31 +152,39 @@ public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
 
         long id = PROXY_CLASS_COUNTER.getAndIncrement();
         String pkg = null;
-        ClassGenerator ccp = null, ccm = null;
+        ClassGenerator ccp = null, // proxy class generator
+                ccm = null; // Proxy class generator
         try {
+            // 创建 proxy 代码生成器
             ccp = ClassGenerator.newInstance(cl);
 
-            Set<String> worked = new HashSet<String>();
-            List<Method> methods = new ArrayList<Method>();
+            Set<String> worked = new HashSet<String>(); // 已处理方法签名集合。key:方法签名
+            List<Method> methods = new ArrayList<Method>(); // 已处理方法集合。
 
+            // 处理接口
             for (int i = 0; i < ics.length; i++) {
+                // 非 public 接口,使用接口包名
                 if (!Modifier.isPublic(ics[i].getModifiers())) {
                     String npkg = ics[i].getPackage().getName();
                     if (pkg == null) {
                         pkg = npkg;
                     } else {
-                        if (!pkg.equals(npkg))
+                        if (!pkg.equals(npkg)) // 实现了两个非 public 的接口,
                             throw new IllegalArgumentException("non-public interfaces from different packages");
                     }
                 }
+                // 添加接口
                 ccp.addInterface(ics[i]);
 
+                // 处理接口方法
                 for (Method method : ics[i].getMethods()) {
+                    // 添加方法签名到已处理方法签名集合
                     String desc = ReflectUtils.getDesc(method);
                     if (worked.contains(desc))
                         continue;
                     worked.add(desc);
 
+                    // 生成接口方法实现代码
                     int ix = methods.size();
                     Class<?> rt = method.getReturnType();
                     Class<?>[] pts = method.getParameterTypes();
@@ -171,31 +197,48 @@ public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
                         code.append(" return ").append(asArgument(rt, "ret")).append(";");
 
                     methods.add(method);
+                    // 添加方法
                     ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString());
                 }
             }
 
+            // 设置包路径
             if (pkg == null)
                 pkg = PACKAGE_NAME;
 
+            // ===== 设置 proxy 代码生成的属性 =====
             // create ProxyInstance class.
+            // 设置类名
             String pcn = pkg + ".proxy" + id;
             ccp.setClassName(pcn);
+            // 添加静态属性 methods
             ccp.addField("public static java.lang.reflect.Method[] methods;");
+            // 添加属性 handler
             ccp.addField("private " + InvocationHandler.class.getName() + " handler;");
+            // 添加构造方法,参数 handler
             ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;");
+            // 添加构造方法,参数 空
             ccp.addDefaultConstructor();
+            // 生成类
             Class<?> clazz = ccp.toClass();
+            // 设置静态属性 methods
             clazz.getField("methods").set(null, methods.toArray(new Method[0]));
 
             // create Proxy class.
+            // 创建 Proxy 代码生成器
             String fcn = Proxy.class.getName() + id;
             ccm = ClassGenerator.newInstance(cl);
+            // 设置类名
             ccm.setClassName(fcn);
+            // 添加构造方法,参数 空
             ccm.addDefaultConstructor();
+            // 设置父类为 Proxy.class
             ccm.setSuperClass(Proxy.class);
+            // 添加方法 #newInstance(handler)
             ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
+            // 生成类
             Class<?> pc = ccm.toClass();
+            // 创建 Proxy 对象
             proxy = (Proxy) pc.newInstance();
         } catch (RuntimeException e) {
             throw e;
@@ -207,6 +250,7 @@ public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
                 ccp.release();
             if (ccm != null)
                 ccm.release();
+            // 唤醒缓存 wait
             synchronized (cache) {
                 if (proxy == null)
                     cache.remove(key);
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Wrapper.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Wrapper.java
index 25ddddb412..9ce3226770 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Wrapper.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/bytecode/Wrapper.java
@@ -23,11 +23,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.regex.Matcher;
@@ -36,38 +32,55 @@
  * Wrapper.
  */
 public abstract class Wrapper {
+
+    /**
+     * Wrapper 对象缓存
+     * key :Wrapper 类。
+     * value :Proxy 对象
+     */
     private static final Map<Class<?>, Wrapper> WRAPPER_MAP = new ConcurrentHashMap<Class<?>, Wrapper>(); //class wrapper map
+
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
     private static final String[] OBJECT_METHODS = new String[]{"getClass", "hashCode", "toString", "equals"};
+
     private static final Wrapper OBJECT_WRAPPER = new Wrapper() {
+
+        @Override
         public String[] getMethodNames() {
             return OBJECT_METHODS;
         }
 
+        @Override
         public String[] getDeclaredMethodNames() {
             return OBJECT_METHODS;
         }
 
+        @Override
         public String[] getPropertyNames() {
             return EMPTY_STRING_ARRAY;
         }
 
+        @Override
         public Class<?> getPropertyType(String pn) {
             return null;
         }
 
+        @Override
         public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException {
             throw new NoSuchPropertyException("Property [" + pn + "] not found.");
         }
 
+        @Override
         public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException {
             throw new NoSuchPropertyException("Property [" + pn + "] not found.");
         }
 
+        @Override
         public boolean hasProperty(String name) {
             return false;
         }
 
+        @Override
         public Object invokeMethod(Object instance, String mn, Class<?>[] types, Object[] args) throws NoSuchMethodException {
             if ("getClass".equals(mn)) return instance.getClass();
             if ("hashCode".equals(mn)) return instance.hashCode();
@@ -78,23 +91,34 @@ public Object invokeMethod(Object instance, String mn, Class<?>[] types, Object[
             }
             throw new NoSuchMethodException("Method [" + mn + "] not found.");
         }
+
     };
+
+    /**
+     * Wrapper Class 计数,用于生成 Wrapper 类名自增。
+     */
     private static AtomicLong WRAPPER_CLASS_COUNTER = new AtomicLong(0);
 
     /**
      * get wrapper.
      *
-     * @param c Class instance.
-     * @return Wrapper instance(not null).
+     * 根据指定类,获得 Wrapper 对象
+     *
+     * @param c Class instance. 指定类
+     * @return Wrapper instance(not null). Wrapper 对象
      */
     public static Wrapper getWrapper(Class<?> c) {
+        // 判断是否继承 ClassGenerator.DC.class ,如果是,拿到父类,避免重复包装
         while (ClassGenerator.isDynamicClass(c)) // can not wrapper on dynamic class.
             c = c.getSuperclass();
 
+        // 指定类为 Object.class
         if (c == Object.class)
             return OBJECT_WRAPPER;
 
+        // 从缓存中获得 Wrapper 对象
         Wrapper ret = WRAPPER_MAP.get(c);
+        // 创建 Wrapper 对象,并添加到缓存
         if (ret == null) {
             ret = makeWrapper(c);
             WRAPPER_MAP.put(c, ret);
@@ -103,52 +127,69 @@ public static Wrapper getWrapper(Class<?> c) {
     }
 
     private static Wrapper makeWrapper(Class<?> c) {
+        // 非私有类
         if (c.isPrimitive())
             throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c);
 
+        // 类名
         String name = c.getName();
+        // 类加载器
         ClassLoader cl = ClassHelper.getClassLoader(c);
 
+        // 设置属性方法 `#setPropertyValue(o, n, v)` 的开头的代码
         StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ ");
+        // 获得属性方法 `#getPropertyValue(o, n)` 的开头的代码
         StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ ");
+        // 调用方法 `#invokeMethod(o, n, p, v)` 的开头的代码
         StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ ");
 
+        // 添加每个方法的,被调用对象的类型转换的代码
         c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
         c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
         c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
 
+        // 属性名与属性名的集合,用于 `#hasProperty(...)` `#setPropertyValue(...)` `getPropertyValue(...)` 方法。
         Map<String, Class<?>> pts = new HashMap<String, Class<?>>(); // <property name, property types>
+        // 方法签名与方法对象的集合,用于 `#invokeMethod(..)` 方法。
         Map<String, Method> ms = new LinkedHashMap<String, Method>(); // <method desc, Method instance>
+        // 方法名数组用于 `#getMethodNames()` 方法。
         List<String> mns = new ArrayList<String>(); // method names.
+        // 定义的方法名数组,用于 `#getDeclaredMethodNames()` 方法。
         List<String> dmns = new ArrayList<String>(); // declaring method names.
 
+        // 循环 public 属性,添加每个属性的设置和获得分别到 `#setPropertyValue(o, n, v)` 和 `#getPropertyValue(o, n)` 的代码
         // get all public field.
         for (Field f : c.getFields()) {
             String fn = f.getName();
             Class<?> ft = f.getType();
-            if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers()))
+            if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers())) // 排除 static 和 transient
                 continue;
 
             c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }");
             c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }");
+            // 添加到 `pts` 中
             pts.put(fn, ft);
         }
 
         Method[] methods = c.getMethods();
+        // 如果有方法,添加 `#invokeMethod(o, n, p, v)` 的 try 的代码
         // get all public method.
         boolean hasMethod = hasMethods(methods);
         if (hasMethod) {
             c3.append(" try{");
         }
         for (Method m : methods) {
+            // 跳过来自 Object 的内置方法
             if (m.getDeclaringClass() == Object.class) //ignore Object's method.
                 continue;
 
-            String mn = m.getName();
+            String mn = m.getName(); // 方法名
+            // 使用方法名 + 方法参数长度来判断
             c3.append(" if( \"").append(mn).append("\".equals( $2 ) ");
             int len = m.getParameterTypes().length;
             c3.append(" && ").append(" $3.length == ").append(len);
 
+            // 若相同方法名存在多个,增加参数类型数组的比较判断
             boolean override = false;
             for (Method m2 : methods) {
                 if (m != m2 && m.getName().equals(m2.getName())) {
@@ -167,6 +208,7 @@ private static Wrapper makeWrapper(Class<?> c) {
 
             c3.append(" ) { ");
 
+            // 添加调用对象的对应方法的代码
             if (m.getReturnType() == Void.TYPE)
                 c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;");
             else
@@ -174,36 +216,44 @@ private static Wrapper makeWrapper(Class<?> c) {
 
             c3.append(" }");
 
+            // 添加到 `mns` 中
             mns.add(mn);
+            // 添加到 `dmns` 中
             if (m.getDeclaringClass() == c)
                 dmns.add(mn);
+            // 添加到 `ms` 中
             ms.put(ReflectUtils.getDesc(m), m);
         }
+        // 如果有方法,添加 `#invokeMethod(o, n, p, v)` 的 catch 的代码
         if (hasMethod) {
             c3.append(" } catch(Throwable e) { ");
             c3.append("     throw new java.lang.reflect.InvocationTargetException(e); ");
             c3.append(" }");
         }
-
+        // 添加 `#invokeMethod(o, n, p, v)` 的未匹配到方法的代码
         c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }");
 
+        // 循环 setting/getting 方法,添加每个属性的设置和获得分别到 `#setPropertyValue(o, n, v)` 和 `#getPropertyValue(o, n)` 的代码
         // deal with get/set method.
         Matcher matcher;
         for (Map.Entry<String, Method> entry : ms.entrySet()) {
             String md = entry.getKey();
-            Method method = (Method) entry.getValue();
+            Method method = entry.getValue();
             if ((matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
                 String pn = propertyName(matcher.group(1));
                 c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
+                // 添加到 `pts` 中
                 pts.put(pn, method.getReturnType());
             } else if ((matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md)).matches()) {
                 String pn = propertyName(matcher.group(1));
                 c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
+                // 添加到 `pts` 中
                 pts.put(pn, method.getReturnType());
-            } else if ((matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
+            } else if ((matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) { // 不支持 public T setName(String name) { this.name = name; return this;} 这种返回 this 的形式。
                 Class<?> pt = method.getParameterTypes()[0];
                 String pn = propertyName(matcher.group(1));
                 c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt, "$3")).append("); return; }");
+                // 添加到 `pts` 中
                 pts.put(pn, pt);
             }
         }
@@ -212,29 +262,49 @@ private static Wrapper makeWrapper(Class<?> c) {
 
         // make class
         long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
+        // 创建 ClassGenerator 对象
         ClassGenerator cc = ClassGenerator.newInstance(cl);
+        // 设置类名
         cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw") + id);
+        // 设置父类为 Wrapper.class
         cc.setSuperClass(Wrapper.class);
 
+        // 添加构造方法,参数 空
         cc.addDefaultConstructor();
+        // 添加静态属性 `pns` 的代码
         cc.addField("public static String[] pns;"); // property name array.
+        // 添加静态属性 `pts` 的代码
         cc.addField("public static " + Map.class.getName() + " pts;"); // property type map.
+        // 添加静态属性 `pts` 的代码
         cc.addField("public static String[] mns;"); // all method name array.
+        // 添加静态属性 `dmns` 的代码
         cc.addField("public static String[] dmns;"); // declared method name array.
+        // 添加静态属性 `mts` 的代码。每个方法的参数数组。
         for (int i = 0, len = ms.size(); i < len; i++)
             cc.addField("public static Class[] mts" + i + ";");
 
+        // ======= 添加抽象方法的实现,到 `cc` 中
+        // 添加 `#getPropertyNames()` 的代码到 `cc`
         cc.addMethod("public String[] getPropertyNames(){ return pns; }");
+        // 添加 `#hasProperty(n)` 的代码到 `cc`
         cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }");
+        // 添加 `#getPropertyType(n)` 的代码到 `cc`
         cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }");
+        // 添加 `#getMethodNames()` 的代码到 `cc`
         cc.addMethod("public String[] getMethodNames(){ return mns; }");
+        // 添加 `#getDeclaredMethodNames()` 的代码到 `cc`
         cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }");
+        // 添加 `#setPropertyValue(o, n, v)` 的代码到 `cc`
         cc.addMethod(c1.toString());
+        // 添加 `#getPropertyValue(o, n)` 的代码到 `cc`
         cc.addMethod(c2.toString());
+        // 添加 `#invokeMethod(o, n, p, v)` 的代码到 `cc`
         cc.addMethod(c3.toString());
 
         try {
+            // 生成类
             Class<?> wc = cc.toClass();
+            // 反射,设置静态变量的值
             // setup static field.
             wc.getField("pts").set(null, pts);
             wc.getField("pns").set(null, pts.keySet().toArray(new String[0]));
@@ -243,12 +313,14 @@ private static Wrapper makeWrapper(Class<?> c) {
             int ix = 0;
             for (Method m : ms.values())
                 wc.getField("mts" + ix++).set(null, m.getParameterTypes());
+            // 创建对象
             return (Wrapper) wc.newInstance();
         } catch (RuntimeException e) {
             throw e;
         } catch (Throwable e) {
             throw new RuntimeException(e.getMessage(), e);
         } finally {
+            // 释放资源
             cc.release();
             ms.clear();
             mns.clear();
@@ -295,12 +367,18 @@ private static String propertyName(String pn) {
         return pn.length() == 1 || Character.isLowerCase(pn.charAt(1)) ? Character.toLowerCase(pn.charAt(0)) + pn.substring(1) : pn;
     }
 
+    /**
+     * 判断是否有方法
+     *
+     * @param methods 方法数组
+     * @return 是否
+     */
     private static boolean hasMethods(Method[] methods) {
         if (methods == null || methods.length == 0) {
             return false;
         }
         for (Method m : methods) {
-            if (m.getDeclaringClass() != Object.class) {
+            if (m.getDeclaringClass() != Object.class) { // 排除内置的方法
                 return true;
             }
         }
@@ -406,11 +484,17 @@ public boolean hasMethod(String name) {
     /**
      * invoke method.
      *
+     * 调用方法
+     *
      * @param instance instance.
+     *                 被调用的对象
      * @param mn       method name.
-     * @param types
+     *                 方法名
+     * @param types 参数类型数组
      * @param args     argument array.
+     *                 参数数组
      * @return return value.
+     *                  返回值
      */
     abstract public Object invokeMethod(Object instance, String mn, Class<?>[] types, Object[] args) throws NoSuchMethodException, InvocationTargetException;
 }
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/Compiler.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/Compiler.java
index 65a719689b..9c617d459a 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/Compiler.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/Compiler.java
@@ -21,6 +21,8 @@
 
 /**
  * Compiler. (SPI, Singleton, ThreadSafe)
+ *
+ * 编辑器接口
  */
 @SPI("javassist")
 public interface Compiler {
@@ -28,9 +30,14 @@
     /**
      * Compile java source code.
      *
+     * 编译 Java 代码字符串
+     *
      * @param code        Java source code
+     *                    Java 代码字符串
      * @param classLoader classloader
+     *                    类加载器
      * @return Compiled class
+     *                    编译后的类
      */
     Class<?> compile(String code, ClassLoader classLoader);
 
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/AbstractCompiler.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/AbstractCompiler.java
index b007244624..1c43ce7697 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/AbstractCompiler.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/AbstractCompiler.java
@@ -24,14 +24,22 @@
 
 /**
  * Abstract compiler. (SPI, Prototype, ThreadSafe)
+ *
+ * Compiler 抽象类
  */
 public abstract class AbstractCompiler implements Compiler {
 
+    /**
+     * 正则 - 包名
+     */
     private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\\s+([$_a-zA-Z][$_a-zA-Z0-9\\.]*);");
-
+    /**
+     * 正则 - 类名
+     */
     private static final Pattern CLASS_PATTERN = Pattern.compile("class\\s+([$_a-zA-Z][$_a-zA-Z0-9]*)\\s+");
 
     public Class<?> compile(String code, ClassLoader classLoader) {
+        // 获得包名
         code = code.trim();
         Matcher matcher = PACKAGE_PATTERN.matcher(code);
         String pkg;
@@ -40,6 +48,7 @@
         } else {
             pkg = "";
         }
+        // 获得类名
         matcher = CLASS_PATTERN.matcher(code);
         String cls;
         if (matcher.find()) {
@@ -47,13 +56,18 @@
         } else {
             throw new IllegalArgumentException("No such class name in " + code);
         }
+        // 获得完整类名
         String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls;
+        // 加载类,若已经存在
         try {
-            return Class.forName(className, true, ClassHelper.getCallerClassLoader(getClass()));
-        } catch (ClassNotFoundException e) {
+            // 加载成功,说明已存在
+            return Class.forName(className, true, ClassHelper.getCallerClassLoader(getClass())); // classloader 为调用方的
+        } catch (ClassNotFoundException e) { // 类不存在,说明可能未编译过,进行编译
+            // 代码格式不正确
             if (!code.endsWith("}")) {
                 throw new IllegalStateException("The java code not endsWith \"}\", code: \n" + code + "\n");
             }
+            // 编译代码
             try {
                 return doCompile(className, code);
             } catch (RuntimeException t) {
@@ -64,6 +78,14 @@
         }
     }
 
+    /**
+     * 编译代码
+     *
+     * @param name 类名
+     * @param source 代码
+     * @return 编译后的类
+     * @throws Throwable 发生异常
+     */
     protected abstract Class<?> doCompile(String name, String source) throws Throwable;
 
 }
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/AdaptiveCompiler.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/AdaptiveCompiler.java
index a088256789..d8f6b2cca9 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/AdaptiveCompiler.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/AdaptiveCompiler.java
@@ -23,26 +23,35 @@
 
 /**
  * AdaptiveCompiler. (SPI, Singleton, ThreadSafe)
+ *
+ * 自适应 Compiler 实现类
  */
 @Adaptive
 public class AdaptiveCompiler implements Compiler {
 
+    /**
+     * 默认编辑器的拓展名
+     */
     private static volatile String DEFAULT_COMPILER;
 
     public static void setDefaultCompiler(String compiler) {
         DEFAULT_COMPILER = compiler;
     }
 
-    public Class<?> compile(String code, ClassLoader classLoader) {
+    @Override public Class<?> compile(String code, ClassLoader classLoader) {
         Compiler compiler;
+        // 获得 Compiler 的 ExtensionLoader 对象。
         ExtensionLoader<Compiler> loader = ExtensionLoader.getExtensionLoader(Compiler.class);
         String name = DEFAULT_COMPILER; // copy reference
+        // 使用设置的拓展名,获得 Compiler 拓展对象
         if (name != null && name.length() > 0) {
             compiler = loader.getExtension(name);
+        // 获得默认的 Compiler 拓展对象
         } else {
             compiler = loader.getDefaultExtension();
         }
+        // 编译类
         return compiler.compile(code, classLoader);
     }
 
-}
+}
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/ClassUtils.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/ClassUtils.java
index a7d574696e..b1d9acdb3c 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/ClassUtils.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/ClassUtils.java
@@ -31,6 +31,8 @@
 
 /**
  * ClassUtils. (Tool, Static, ThreadSafe)
+ *
+ * 类工具类
  */
 public class ClassUtils {
 
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JavassistCompiler.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JavassistCompiler.java
index 25d95be497..3d39a2f982 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JavassistCompiler.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JavassistCompiler.java
@@ -37,88 +37,112 @@
  */
 public class JavassistCompiler extends AbstractCompiler {
 
+    /**
+     * 正则 - 匹配 import
+     */
     private static final Pattern IMPORT_PATTERN = Pattern.compile("import\\s+([\\w\\.\\*]+);\n");
-
+    /**
+     * 正则 - 匹配 extends
+     */
     private static final Pattern EXTENDS_PATTERN = Pattern.compile("\\s+extends\\s+([\\w\\.]+)[^\\{]*\\{\n");
-
+    /**
+     * 正则 - 匹配 implements
+     */
     private static final Pattern IMPLEMENTS_PATTERN = Pattern.compile("\\s+implements\\s+([\\w\\.]+)\\s*\\{\n");
-
+    /**
+     * 正则 - 匹配方法
+     */
     private static final Pattern METHODS_PATTERN = Pattern.compile("\n(private|public|protected)\\s+");
-
+    /**
+     * 正则 - 匹配变量
+     */
     private static final Pattern FIELD_PATTERN = Pattern.compile("[^\n]+=[^\n]+;");
 
     @Override
     public Class<?> doCompile(String name, String source) throws Throwable {
+        // 获得类名
         int i = name.lastIndexOf('.');
         String className = i < 0 ? name : name.substring(i + 1);
+        // 创建 ClassPool 对象
         ClassPool pool = new ClassPool(true);
+        // 设置类搜索路径
         pool.appendClassPath(new LoaderClassPath(ClassHelper.getCallerClassLoader(getClass())));
+        // 匹配 import
         Matcher matcher = IMPORT_PATTERN.matcher(source);
-        List<String> importPackages = new ArrayList<String>();
-        Map<String, String> fullNames = new HashMap<String, String>();
+        List<String> importPackages = new ArrayList<String>(); // 引用的包名
+        Map<String, String> fullNames = new HashMap<String, String>(); // 引用的类名
         while (matcher.find()) {
             String pkg = matcher.group(1);
-            if (pkg.endsWith(".*")) {
+            if (pkg.endsWith(".*")) { // 引用整个包下的类/接口
                 String pkgName = pkg.substring(0, pkg.length() - 2);
                 pool.importPackage(pkgName);
                 importPackages.add(pkgName);
-            } else {
+            } else { // 引用指定类/接口
                 int pi = pkg.lastIndexOf('.');
                 if (pi > 0) {
                     String pkgName = pkg.substring(0, pi);
                     pool.importPackage(pkgName);
                     importPackages.add(pkgName);
-                    fullNames.put(pkg.substring(pi + 1), pkg);
+                    fullNames.put(pkg.substring(pi + 1), pkg); // 类名
                 }
             }
         }
         String[] packages = importPackages.toArray(new String[0]);
+        // 匹配 extends
         matcher = EXTENDS_PATTERN.matcher(source);
         CtClass cls;
         if (matcher.find()) {
             String extend = matcher.group(1).trim();
             String extendClass;
-            if (extend.contains(".")) {
+            if (extend.contains(".")) { // 内嵌的类,例如:extends A.B
                 extendClass = extend;
-            } else if (fullNames.containsKey(extend)) {
+            } else if (fullNames.containsKey(extend)) { // 指定引用的类
                 extendClass = fullNames.get(extend);
-            } else {
+            } else { // 引用整个包下的类
                 extendClass = ClassUtils.forName(packages, extend).getName();
             }
+            // 创建 CtClass 对象
             cls = pool.makeClass(name, pool.get(extendClass));
         } else {
+            // 创建 CtClass 对象
             cls = pool.makeClass(name);
         }
+        // 匹配 implements
         matcher = IMPLEMENTS_PATTERN.matcher(source);
         if (matcher.find()) {
             String[] ifaces = matcher.group(1).trim().split("\\,");
             for (String iface : ifaces) {
                 iface = iface.trim();
                 String ifaceClass;
-                if (iface.contains(".")) {
+                if (iface.contains(".")) { // 内嵌的接口,例如:extends A.B
                     ifaceClass = iface;
-                } else if (fullNames.containsKey(iface)) {
+                } else if (fullNames.containsKey(iface)) { // 指定引用的接口
                     ifaceClass = fullNames.get(iface);
-                } else {
+                } else { // 引用整个包下的接口
                     ifaceClass = ClassUtils.forName(packages, iface).getName();
                 }
+                // 添加接口
                 cls.addInterface(pool.get(ifaceClass));
             }
         }
+        // 获得类中的内容,即首末 {} 的内容。
         String body = source.substring(source.indexOf("{") + 1, source.length() - 1);
+        // 匹配 method 。使用分隔的方式,实际上,分隔出来的不仅仅有方法。
         String[] methods = METHODS_PATTERN.split(body);
         for (String method : methods) {
             method = method.trim();
             if (method.length() > 0) {
-                if (method.startsWith(className)) {
+                if (method.startsWith(className)) { // 构造方法
                     cls.addConstructor(CtNewConstructor.make("public " + method, cls));
-                } else if (FIELD_PATTERN.matcher(method).matches()) {
+                } else if (FIELD_PATTERN.matcher(method).matches()) { // 变量
                     cls.addField(CtField.make("private " + method, cls));
-                } else {
+                } else { // 方法
                     cls.addMethod(CtNewMethod.make("public " + method, cls));
                 }
             }
         }
+        // 生成类
+        // JavassistCompiler.class.getProtectionDomain() =》 设置保护域和 JavassistCompiler 一致,即 `#getClass()` 方法。深入见 《Java安全——安全管理器、访问控制器和类装载器》https://www.zybuluo.com/changedi/note/417132
         return cls.toClass(ClassHelper.getCallerClassLoader(getClass()), JavassistCompiler.class.getProtectionDomain());
     }
 
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JdkCompiler.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JdkCompiler.java
index 461172d780..ed6f0ab319 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JdkCompiler.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/compiler/support/JdkCompiler.java
@@ -55,6 +55,11 @@
  */
 public class JdkCompiler extends AbstractCompiler {
 
+    /**
+     * 获得系统的 Java 编译器
+     *
+     * 笔者的理解是,javac
+     */
     private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 
     private final DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<JavaFileObject>();
@@ -62,15 +67,19 @@
     private final ClassLoaderImpl classLoader;
 
     private final JavaFileManagerImpl javaFileManager;
-
+    /**
+     * 编译选项
+     */
     private volatile List<String> options;
 
     public JdkCompiler() {
+        // 设置编译选项,Dubbo 基于 JDK 1.6 的版本
         options = new ArrayList<String>();
         options.add("-source");
         options.add("1.6");
         options.add("-target");
         options.add("1.6");
+        // TODO
         StandardJavaFileManager manager = compiler.getStandardFileManager(diagnosticCollector, null, null);
         final ClassLoader loader = Thread.currentThread().getContextClassLoader();
         if (loader instanceof URLClassLoader
@@ -86,33 +95,50 @@ public JdkCompiler() {
                 throw new IllegalStateException(e.getMessage(), e);
             }
         }
+        // TODO
         classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoaderImpl>() {
             public ClassLoaderImpl run() {
                 return new ClassLoaderImpl(loader);
             }
         });
+        // TODO
         javaFileManager = new JavaFileManagerImpl(manager, classLoader);
     }
 
     @Override
     public Class<?> doCompile(String name, String sourceCode) throws Throwable {
+        // 获得包名、类名
         int i = name.lastIndexOf('.');
         String packageName = i < 0 ? "" : name.substring(0, i);
         String className = i < 0 ? name : name.substring(i + 1);
+        // 创建 JavaFileObjectImpl 对象
         JavaFileObjectImpl javaFileObject = new JavaFileObjectImpl(className, sourceCode);
+        // TODO
         javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName,
                 className + ClassUtils.JAVA_EXTENSION, javaFileObject);
+        // 编译
         Boolean result = compiler.getTask(null, javaFileManager, diagnosticCollector, options,
                 null, Arrays.asList(javaFileObject)).call();
+        // 编译失败,抛出异常
         if (result == null || !result) {
             throw new IllegalStateException("Compilation failed. class: " + name + ", diagnostics: " + diagnosticCollector);
         }
+        // 编译成功,类加载
         return classLoader.loadClass(name);
     }
 
+    /**
+     * 用 JavaFileObjectImpl 替换 JDK 默认的 SimpleJavaFileObject,以便在接收到编译器生成的 byte[] 内容时,不写入 class 文件,而是直接保存在内存中。
+     */
     private static final class JavaFileObjectImpl extends SimpleJavaFileObject {
 
+        /**
+         * Java 源代码
+         */
         private final CharSequence source;
+        /**
+         * Java 源代码转成的二进制输出流
+         */
         private ByteArrayOutputStream bytecode;
 
         public JavaFileObjectImpl(final String baseName, final CharSequence source) {
@@ -153,6 +179,9 @@ public OutputStream openOutputStream() {
         }
     }
 
+    /**
+     *
+     */
     private static final class JavaFileManagerImpl extends ForwardingJavaFileManager<JavaFileManager> {
 
         private final ClassLoaderImpl classLoader;
@@ -181,8 +210,7 @@ private URI uri(Location location, String packageName, String relativeName) {
         }
 
         @Override
-        public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, Kind kind, FileObject outputFile)
-                throws IOException {
+        public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, Kind kind, FileObject outputFile) {
             JavaFileObject file = new JavaFileObjectImpl(qualifiedName, kind);
             classLoader.add(qualifiedName, file);
             return file;
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Activate.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Activate.java
index 7db8fe10a2..79641126dd 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Activate.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Activate.java
@@ -39,6 +39,27 @@
  * @see URL
  * @see ExtensionLoader
  */
+/**
+ * Activate
+ * <p/>
+ * 对于可以被框架中自动激活加载扩展,此 Annotation 用于配置扩展被自动激活加载条件。
+ * 比如,过滤扩展,有多个实现,使用 Activate Annotation 的扩展可以根据条件被自动加载。
+ * <ol>
+ *      <li>{@link Activate#group() }生效的Group。具体的有哪些Group值由框架SPI给出。
+ *      <li>{@link Activate#value()} 在 {@link com.alibaba.dubbo.common.URL} 中Key集合中有,则生效。
+ * </ol>
+ * <p>
+ * <p/>
+ * 底层框架SPI提供者通过 {@link com.alibaba.dubbo.common.extension.ExtensionLoader} 的 {@link ExtensionLoader#getActivateExtension} 方法
+ * 获得条件的扩展。
+ *
+ * @author william.liangf
+ * @author ding.lid
+ * @export
+ * @see SPI
+ * @see ExtensionLoader
+ * @see ExtensionLoader#getActivateExtension(com.alibaba.dubbo.common.URL, String[], String)
+ */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.TYPE, ElementType.METHOD})
@@ -50,6 +71,13 @@
      * @return group names to match
      * @see ExtensionLoader#getActivateExtension(URL, String, String)
      */
+    /**
+     * Group过滤条件。
+     * <br />
+     * 包含{@link ExtensionLoader#getActivateExtension}的group参数给的值,则返回扩展。
+     * <br />
+     * 如没有Group设置,则不过滤。
+     */
     String[] group() default {};
 
     /**
@@ -63,6 +91,15 @@
      * @see ExtensionLoader#getActivateExtension(URL, String)
      * @see ExtensionLoader#getActivateExtension(URL, String, String)
      */
+    /**
+     * Key过滤条件。包含{@link ExtensionLoader#getActivateExtension}的URL的参数Key中有,则返回扩展。
+     * <p/>
+     * 示例:<br/>
+     * 注解的值 <code>@Activate("cache,validatioin")</code>,
+     * 则{@link ExtensionLoader#getActivateExtension}的URL的参数有<code>cache</code>Key,或是<code>validatioin</code>则返回扩展。
+     * <br/>
+     * 如没有设置,则不过滤。
+     */
     String[] value() default {};
 
     /**
@@ -70,6 +107,9 @@
      *
      * @return extension list which should be put before the current one
      */
+    /**
+     * 排序信息,可以不提供。
+     */
     String[] before() default {};
 
     /**
@@ -77,6 +117,9 @@
      *
      * @return extension list which should be put after the current one
      */
+    /**
+     * 排序信息,可以不提供。
+     */
     String[] after() default {};
 
     /**
@@ -84,5 +127,8 @@
      *
      * @return absolute ordering info
      */
+    /**
+     * 排序信息,可以不提供。
+     */
     int order() default 0;
 }
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Adaptive.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Adaptive.java
index d7cc208333..c6f6c5aa27 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Adaptive.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/Adaptive.java
@@ -27,6 +27,15 @@
 /**
  * Provide helpful information for {@link ExtensionLoader} to inject dependency extension instance.
  *
+ * 在 {@link ExtensionLoader} 生成 Extension 的 Adaptive Instance 时,为 {@link ExtensionLoader} 提供信息。
+ *
+ * `@Adaptive` 可添加类或方法上。这两种方式表现不同:
+ *
+ * 1. 当在 类 上时,直接使用被注解的类。也因此,一个拓展,只允许最多注解一个类,否则会存在多个会是冲突。
+ * 2. 当在方法上时,使用 {@link ExtensionLoader#createAdaptiveExtensionClass()} 方法,创建自适应( Adaptive )拓展类。
+ *
+ * 如上逻辑,处理的入口方法为 {@link ExtensionLoader#getAdaptiveExtensionClass()}
+ *
  * @see ExtensionLoader
  * @see URL
  */
@@ -34,6 +43,7 @@
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.TYPE, ElementType.METHOD})
 public @interface Adaptive {
+
     /**
      * Decide which target extension to be injected. The name of the target extension is decided by the parameter passed
      * in the URL, and the parameter names are given by this method.
@@ -55,6 +65,23 @@
      *
      * @return parameter key names in URL
      */
+    /**
+     * 从 {@link URL }的 Key 名,对应的 Value 作为要 Adapt 成的 Extension 名。
+     * <p>
+     * 如果 {@link URL} 这些 Key 都没有 Value ,使用 缺省的扩展(在接口的{@link SPI}中设定的值)。<br>
+     * 比如,<code>String[] {"key1", "key2"}</code>,表示
+     * <ol>
+     *      <li>先在URL上找key1的Value作为要Adapt成的Extension名;
+     *      <li>key1没有Value,则使用key2的Value作为要Adapt成的Extension名。
+     *      <li>key2没有Value,使用缺省的扩展。
+     *      <li>如果没有设定缺省扩展,则方法调用会抛出{@link IllegalStateException}。
+     * </ol>
+     * <p>
+     * 如果不设置则缺省使用Extension接口类名的点分隔小写字串。<br>
+     * 即对于Extension接口 {@code com.alibaba.dubbo.xxx.YyyInvokerWrapper} 的缺省值为 <code>String[] {"yyy.invoker.wrapper"}</code>
+     *
+     * @see SPI#value()
+     */
     String[] value() default {};
 
 }
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionFactory.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionFactory.java
index 4cfc7a7d7d..ff94bf6314 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionFactory.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionFactory.java
@@ -18,6 +18,8 @@
 
 /**
  * ExtensionFactory
+ *
+ * 拓展工厂接口
  */
 @SPI
 public interface ExtensionFactory {
@@ -25,9 +27,11 @@
     /**
      * Get extension.
      *
-     * @param type object type.
-     * @param name object name.
-     * @return object instance.
+     * 获得拓展对象
+     *
+     * @param type object type. 拓展接口
+     * @param name object name. 拓展名
+     * @return object instance. 拓展对象
      */
     <T> T getExtension(Class<T> type, String name);
 
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java
index 8013571547..cf92cf029d 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/ExtensionLoader.java
@@ -30,15 +30,7 @@
 import java.io.InputStreamReader;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.regex.Pattern;
@@ -51,11 +43,26 @@
  * <li>default extension is an adaptive instance</li>
  * </ul>
  *
+ * 拓展加载器
+ *
+ * Dubbo使用的扩展点获取。<p>
+ * <ul>
+ *      <li>自动注入关联扩展点。</li>
+ *      <li>自动Wrap上扩展点的Wrap类。</li>
+ *      <li>缺省获得的的扩展点是一个Adaptive Instance。</li>
+ * </ul>
+ *
+ * Dubbo SPI :https://dubbo.gitbooks.io/dubbo-dev-book/SPI.html
+ * Java  SPI :http://blog.csdn.net/top_code/article/details/51934459
+ *
+ * 另外,该类同时是 ExtensionLoader 的管理容器,例如 {@link #EXTENSION_INSTANCES} 、{@link #EXTENSION_INSTANCES} 属性。
+ *
  * @see <a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">Service Provider in Java 5</a>
  * @see com.alibaba.dubbo.common.extension.SPI
  * @see com.alibaba.dubbo.common.extension.Adaptive
  * @see com.alibaba.dubbo.common.extension.Activate
  */
+@SuppressWarnings("deprecation")
 public class ExtensionLoader<T> {
 
     private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);
@@ -68,29 +75,121 @@
 
     private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
 
-    private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
+    // ============================== 静态属性 ==============================
 
+    /**
+     * 拓展加载器集合
+     *
+     * key:拓展接口
+     */
+    private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
+    /**
+     * 拓展实现类集合
+     *
+     * key:拓展实现类
+     * value:拓展对象。
+     *
+     * 例如,key 为 Class<AccessLogFilter>
+     *      value 为 AccessLogFilter 对象
+     */
     private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();
 
-    // ==============================
+    // ============================== 对象属性 ==============================
 
+    /**
+     * 拓展接口。
+     * 例如,Protocol
+     */
     private final Class<?> type;
-
+    /**
+     * 对象工厂
+     *
+     * 用于调用 {@link #injectExtension(Object)} 方法,向拓展对象注入依赖的属性。
+     *
+     * 例如,StubProxyFactoryWrapper 中有 `Protocol protocol` 属性。
+     */
     private final ExtensionFactory objectFactory;
-
+    /**
+     * 缓存的拓展名与拓展类的映射。
+     *
+     * 和 {@link #cachedClasses} 的 KV 对调。
+     *
+     * 通过 {@link #loadExtensionClasses} 加载
+     */
     private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();
-
+    /**
+     * 缓存的拓展实现类集合。
+     *
+     * 不包含如下两种类型:
+     *  1. 自适应拓展实现类。例如 AdaptiveExtensionFactory
+     *  2. 带唯一参数为拓展接口的构造方法的实现类,或者说拓展 Wrapper 实现类。例如,ProtocolFilterWrapper 。
+     *       拓展 Wrapper 实现类,会添加到 {@link #cachedWrapperClasses} 中
+     *
+     * 通过 {@link #loadExtensionClasses} 加载
+     */
     private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>();
 
+    /**
+     * 拓展名与 @Activate 的映射
+     *
+     * 例如,AccessLogFilter。
+     *
+     * 用于 {@link #getActivateExtension(URL, String)}
+     */
     private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();
+    /**
+     * 缓存的拓展对象集合
+     *
+     * key:拓展名
+     * value:拓展对象
+     *
+     * 例如,Protocol 拓展
+     *          key:dubbo value:DubboProtocol
+     *          key:injvm value:InjvmProtocol
+     *
+     * 通过 {@link #loadExtensionClasses} 加载
+     */
     private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
+    /**
+     * 缓存的自适应( Adaptive )拓展对象
+     */
     private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
+    /**
+     * 缓存的自适应拓展对象的类
+     *
+     * {@link #getAdaptiveExtensionClass()}
+     */
     private volatile Class<?> cachedAdaptiveClass = null;
+    /**
+     * 缓存的默认拓展名
+     *
+     * 通过 {@link SPI} 注解获得
+     */
     private String cachedDefaultName;
+    /**
+     * 创建 {@link #cachedAdaptiveInstance} 时发生的异常。
+     *
+     * 发生异常后,不再创建,参见 {@link #createAdaptiveExtension()}
+     */
     private volatile Throwable createAdaptiveInstanceError;
 
+    /**
+     * 拓展 Wrapper 实现类集合
+     *
+     * 带唯一参数为拓展接口的构造方法的实现类
+     *
+     * 通过 {@link #loadExtensionClasses} 加载
+     */
     private Set<Class<?>> cachedWrapperClasses;
 
+    /**
+     * 拓展名 与 加载对应拓展类发生的异常 的 映射
+     *
+     * key:拓展名
+     * value:异常
+     *
+     * 在 {@link #loadFile(Map, String)} 时,记录
+     */
     private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();
 
     private ExtensionLoader(Class<?> type) {
@@ -98,22 +197,39 @@ private ExtensionLoader(Class<?> type) {
         objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
     }
 
+    /**
+     * 是否包含 @SPI 注解
+     *
+     * @param type 类
+     * @param <T> 泛型
+     * @return 是否包含
+     */
     private static <T> boolean withExtensionAnnotation(Class<T> type) {
         return type.isAnnotationPresent(SPI.class);
     }
 
+    /**
+     * 根据拓展点的接口,获得拓展加载器
+     *
+     * @param type 接口
+     * @param <T> 泛型
+     * @return 加载器
+     */
     @SuppressWarnings("unchecked")
     public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
         if (type == null)
             throw new IllegalArgumentException("Extension type == null");
+        // 必须是接口
         if (!type.isInterface()) {
             throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
         }
+        // 必须包含 @SPI 注解
         if (!withExtensionAnnotation(type)) {
             throw new IllegalArgumentException("Extension type(" + type +
                     ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
         }
 
+        // 获得接口对应的拓展点加载器
         ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
         if (loader == null) {
             EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
@@ -161,20 +277,28 @@ public String getExtensionName(Class<?> extensionClass) {
     /**
      * This is equivalent to {@code getActivateExtension(url, url.getParameter(key).split(","), null)}
      *
+     * 获得符合自动激活条件的拓展对象数组
+     *
      * @param url   url
      * @param key   url parameter key which used to get extension point names
+     *              Dubbo URL 参数名
      * @param group group
+     *              过滤分组名
      * @return extension list which are activated.
      * @see #getActivateExtension(com.alibaba.dubbo.common.URL, String[], String)
      */
     public List<T> getActivateExtension(URL url, String key, String group) {
+        // 从 Dubbo URL 获得参数值
         String value = url.getParameter(key);
+        // 获得符合自动激活条件的拓展对象数组
         return getActivateExtension(url, value == null || value.length() == 0 ? null : Constants.COMMA_SPLIT_PATTERN.split(value), group);
     }
 
     /**
      * Get activate extensions.
      *
+     * 获得符合自动激活条件的拓展对象数组
+     *
      * @param url    url
      * @param values extension point names
      * @param group  group
@@ -184,48 +308,66 @@ public String getExtensionName(Class<?> extensionClass) {
     public List<T> getActivateExtension(URL url, String[] values, String group) {
         List<T> exts = new ArrayList<T>();
         List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values);
+        // 处理自动激活的拓展对象们
+        // 判断不存在配置 `"-name"` 。例如,<dubbo:service filter="-default" /> ,代表移除所有默认过滤器。
         if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) {
+            // 获得拓展实现类数组
             getExtensionClasses();
+            // 循环
             for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) {
                 String name = entry.getKey();
                 Activate activate = entry.getValue();
-                if (isMatchGroup(group, activate.group())) {
+                if (isMatchGroup(group, activate.group())) { // 匹配分组
+                    // 获得拓展对象
                     T ext = getExtension(name);
-                    if (!names.contains(name)
-                            && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)
-                            && isActive(activate, url)) {
+                    if (!names.contains(name) // 不包含在自定义配置里。如果包含,会在下面的代码处理。
+                            && !names.contains(Constants.REMOVE_VALUE_PREFIX + name) // 判断是否配置移除。例如 <dubbo:service filter="-monitor" />,则 MonitorFilter 会被移除
+                            && isActive(activate, url)) { // 判断是否激活
                         exts.add(ext);
                     }
                 }
             }
+            // 排序
             Collections.sort(exts, ActivateComparator.COMPARATOR);
         }
+        // 处理自定义配置的拓展对象们。例如在 <dubbo:service filter="demo" /> ,代表需要加入 DemoFilter (这个是笔者自定义的)。
         List<T> usrs = new ArrayList<T>();
         for (int i = 0; i < names.size(); i++) {
             String name = names.get(i);
-            if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX)
-                    && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) {
+            if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX) && !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) { // 判断非移除的
+                // 将配置的自定义在自动激活的拓展对象们前面。例如,<dubbo:service filter="demo,default,demo2" /> ,则 DemoFilter 就会放在默认的过滤器前面。
                 if (Constants.DEFAULT_KEY.equals(name)) {
                     if (!usrs.isEmpty()) {
                         exts.addAll(0, usrs);
                         usrs.clear();
                     }
                 } else {
+                    // 获得拓展对象
                     T ext = getExtension(name);
                     usrs.add(ext);
                 }
             }
         }
+        // 添加到结果集
         if (!usrs.isEmpty()) {
             exts.addAll(usrs);
         }
         return exts;
     }
 
+    /**
+     * 匹配分组
+     *
+     * @param group 过滤的分组条件。若为空,无需过滤
+     * @param groups 配置的分组
+     * @return 是否匹配
+     */
     private boolean isMatchGroup(String group, String[] groups) {
+        // 为空,无需过滤
         if (group == null || group.length() == 0) {
             return true;
         }
+        // 匹配
         if (groups != null && groups.length > 0) {
             for (String g : groups) {
                 if (group.equals(g)) {
@@ -236,9 +378,16 @@ private boolean isMatchGroup(String group, String[] groups) {
         return false;
     }
 
+    /**
+     * 是否激活,通过 Dubbo URL 中是否存在参数名为 `@Activate.value` ,并且参数值非空。
+     *
+     * @param activate 自动激活注解
+     * @param url Dubbo URL
+     * @return 是否
+     */
     private boolean isActive(Activate activate, URL url) {
         String[] keys = activate.value();
-        if (keys == null || keys.length == 0) {
+        if (keys.length == 0) {
             return true;
         }
         for (String key : keys) {
@@ -262,6 +411,13 @@ private boolean isActive(Activate activate, URL url) {
      *
      * @see #getExtension(String)
      */
+    /**
+     * 返回扩展点实例,如果没有指定的扩展点或是还没加载(即实例化)则返回<code>null</code>。注意:此方法不会触发扩展点的加载。
+     * <p/>
+     * 一般应该调用{@link #getExtension(String)}方法获得扩展,这个方法会触发扩展点加载。
+     *
+     * @see #getExtension(String)
+     */
     @SuppressWarnings("unchecked")
     public T getLoadedExtension(String name) {
         if (name == null || name.length() == 0)
@@ -281,6 +437,13 @@ public T getLoadedExtension(String name) {
      *
      * @see #getSupportedExtensions()
      */
+    /**
+     * 返回已经加载的扩展点的名字。
+     * <p/>
+     * 一般应该调用{@link #getSupportedExtensions()}方法获得扩展,这个方法会返回所有的扩展点。
+     *
+     * @see #getSupportedExtensions()
+     */
     public Set<String> getLoadedExtensions() {
         return Collections.unmodifiableSet(new TreeSet<String>(cachedInstances.keySet()));
     }
@@ -289,13 +452,21 @@ public T getLoadedExtension(String name) {
      * Find the extension with the given name. If the specified name is not found, then {@link IllegalStateException}
      * will be thrown.
      */
+    /**
+     * 返回指定名字的扩展对象。如果指定名字的扩展不存在,则抛异常 {@link IllegalStateException}.
+     *
+     * @param name 拓展名
+     * @return 拓展对象
+     */
     @SuppressWarnings("unchecked")
     public T getExtension(String name) {
         if (name == null || name.length() == 0)
             throw new IllegalArgumentException("Extension name == null");
+        // 查找 默认的 拓展对象
         if ("true".equals(name)) {
             return getDefaultExtension();
         }
+        // 从 缓存中 获得对应的拓展对象
         Holder<Object> holder = cachedInstances.get(name);
         if (holder == null) {
             cachedInstances.putIfAbsent(name, new Holder<Object>());
@@ -305,8 +476,10 @@ public T getExtension(String name) {
         if (instance == null) {
             synchronized (holder) {
                 instance = holder.get();
+                // 从 缓存中 未获取到,进行创建缓存对象。
                 if (instance == null) {
                     instance = createExtension(name);
+                    // 设置创建对象到缓存中
                     holder.set(instance);
                 }
             }
@@ -317,10 +490,13 @@ public T getExtension(String name) {
     /**
      * Return default extension, return <code>null</code> if it's not configured.
      */
+    /**
+     * 返回缺省的扩展,如果没有设置则返回<code>null</code>。
+     */
     public T getDefaultExtension() {
         getExtensionClasses();
         if (null == cachedDefaultName || cachedDefaultName.length() == 0
-                || "true".equals(cachedDefaultName)) {
+                || "true".equals(cachedDefaultName)) { // 如果为 true ,不能继续调用 `#getExtension(true)` 方法,会形成死循环。
             return null;
         }
         return getExtension(cachedDefaultName);
@@ -344,6 +520,9 @@ public boolean hasExtension(String name) {
     /**
      * Return default extension name, return <code>null</code> if not configured.
      */
+    /**
+     * 返回缺省的扩展点名,如果没有设置缺省则返回<code>null</code>。
+     */
     public String getDefaultExtensionName() {
         getExtensionClasses();
         return cachedDefaultName;
@@ -356,6 +535,13 @@ public String getDefaultExtensionName() {
      * @param clazz extension class
      * @throws IllegalStateException when extension with the same name has already been registered.
      */
+    /**
+     * 编程方式添加新扩展点。
+     *
+     * @param name  扩展点名
+     * @param clazz 扩展点类
+     * @throws IllegalStateException 要添加扩展点名已经存在。
+     */
     public void addExtension(String name, Class<?> clazz) {
         getExtensionClasses(); // load classes
 
@@ -396,6 +582,14 @@ public void addExtension(String name, Class<?> clazz) {
      * @throws IllegalStateException when extension to be placed doesn't exist
      * @deprecated not recommended any longer, and use only when test
      */
+    /**
+     * 编程方式添加替换已有扩展点。
+     *
+     * @param name  扩展点名
+     * @param clazz 扩展点类
+     * @throws IllegalStateException 要添加扩展点名已经存在。
+     * @deprecated 不推荐应用使用,一般只在测试时可以使用
+     */
     @Deprecated
     public void replaceExtension(String name, Class<?> clazz) {
         getExtensionClasses(); // load classes
@@ -431,46 +625,61 @@ public void replaceExtension(String name, Class<?> clazz) {
         }
     }
 
+    /**
+     * 获得自适应拓展对象
+     *
+     * @return 拓展对象
+     */
     @SuppressWarnings("unchecked")
     public T getAdaptiveExtension() {
+        // 从缓存中,获得自适应拓展对象
         Object instance = cachedAdaptiveInstance.get();
         if (instance == null) {
+            // 若之前未创建报错,
             if (createAdaptiveInstanceError == null) {
                 synchronized (cachedAdaptiveInstance) {
                     instance = cachedAdaptiveInstance.get();
                     if (instance == null) {
                         try {
+                            // 创建自适应拓展对象
                             instance = createAdaptiveExtension();
+                            // 设置到缓存
                             cachedAdaptiveInstance.set(instance);
                         } catch (Throwable t) {
+                            // 记录异常
                             createAdaptiveInstanceError = t;
                             throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
                         }
                     }
                 }
+            // 若之前创建报错,则抛出异常 IllegalStateException
             } else {
                 throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
             }
         }
-
         return (T) instance;
     }
 
+    /**
+     * 获得拓展名不存在时的异常
+     *
+     * @param name 拓展名
+     * @return 异常
+     */
     private IllegalStateException findException(String name) {
+        // 在 `#loadFile(...)` 方法中,加载时,发生异常
         for (Map.Entry<String, IllegalStateException> entry : exceptions.entrySet()) {
             if (entry.getKey().toLowerCase().contains(name.toLowerCase())) {
                 return entry.getValue();
             }
         }
+        // 生成不存在该拓展类实现的异常。
         StringBuilder buf = new StringBuilder("No such extension " + type.getName() + " by name " + name);
-
-
         int i = 1;
         for (Map.Entry<String, IllegalStateException> entry : exceptions.entrySet()) {
             if (i == 1) {
                 buf.append(", possible causes: ");
             }
-
             buf.append("\r\n(");
             buf.append(i++);
             buf.append(") ");
@@ -481,19 +690,30 @@ private IllegalStateException findException(String name) {
         return new IllegalStateException(buf.toString());
     }
 
+    /**
+     * 创建拓展名的拓展对象,并缓存。
+     *
+     * @param name 拓展名
+     * @return 拓展对象
+     */
     @SuppressWarnings("unchecked")
     private T createExtension(String name) {
+        // 获得拓展名对应的拓展实现类
         Class<?> clazz = getExtensionClasses().get(name);
         if (clazz == null) {
-            throw findException(name);
+            throw findException(name); // 抛出异常
         }
         try {
+            // 从缓存中,获得拓展对象。
             T instance = (T) EXTENSION_INSTANCES.get(clazz);
             if (instance == null) {
-                EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
+                // 当缓存不存在时,创建拓展对象,并添加到缓存中。
+                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
                 instance = (T) EXTENSION_INSTANCES.get(clazz);
             }
+            // 注入依赖的属性
             injectExtension(instance);
+            // 创建 Wrapper 拓展对象
             Set<Class<?>> wrapperClasses = cachedWrapperClasses;
             if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
                 for (Class<?> wrapperClass : wrapperClasses) {
@@ -507,17 +727,27 @@ private T createExtension(String name) {
         }
     }
 
+    /**
+     * 注入依赖的属性
+     *
+     * @param instance 拓展对象
+     * @return 拓展对象
+     */
     private T injectExtension(T instance) {
         try {
             if (objectFactory != null) {
                 for (Method method : instance.getClass().getMethods()) {
                     if (method.getName().startsWith("set")
                             && method.getParameterTypes().length == 1
-                            && Modifier.isPublic(method.getModifiers())) {
+                            && Modifier.isPublic(method.getModifiers())) { // setting && public 方法
+                        // 获得属性的类型
                         Class<?> pt = method.getParameterTypes()[0];
                         try {
+                            // 获得属性
                             String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
+                            // 获得属性值
                             Object object = objectFactory.getExtension(pt, property);
+                            // 设置属性值
                             if (object != null) {
                                 method.invoke(instance, object);
                             }
@@ -539,19 +769,28 @@ private T injectExtension(T instance) {
             throw new IllegalArgumentException("Extension type == null");
         if (name == null)
             throw new IllegalArgumentException("Extension name == null");
+        // 获得拓展实现类
         Class<?> clazz = getExtensionClasses().get(name);
         if (clazz == null)
             throw new IllegalStateException("No such extension \"" + name + "\" for " + type.getName() + "!");
         return clazz;
     }
 
+    /**
+     * 获得拓展实现类数组
+     *
+     * @return 拓展实现类数组
+     */
     private Map<String, Class<?>> getExtensionClasses() {
+        // 从缓存中,获得拓展实现类数组
         Map<String, Class<?>> classes = cachedClasses.get();
         if (classes == null) {
             synchronized (cachedClasses) {
                 classes = cachedClasses.get();
                 if (classes == null) {
+                    // 从配置文件中,加载拓展实现类数组
                     classes = loadExtensionClasses();
+                    // 设置到缓存中
                     cachedClasses.set(classes);
                 }
             }
@@ -559,12 +798,20 @@ private T injectExtension(T instance) {
         return classes;
     }
 
-    // synchronized in getExtensionClasses
+    /**
+     * 加载拓展实现类数组
+     *
+     * 无需声明 synchronized ,因为唯一调用该方法的 {@link #getExtensionClasses()} 已经声明。
+     * // synchronized in getExtensionClasses
+     *
+     * @return 拓展实现类数组
+     */
     private Map<String, Class<?>> loadExtensionClasses() {
+        // 通过 @SPI 注解,获得默认的拓展实现类名
         final SPI defaultAnnotation = type.getAnnotation(SPI.class);
         if (defaultAnnotation != null) {
             String value = defaultAnnotation.value();
-            if (value != null && (value = value.trim()).length() > 0) {
+            if ((value = value.trim()).length() > 0) {
                 String[] names = NAME_SEPARATOR.split(value);
                 if (names.length > 1) {
                     throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
@@ -574,6 +821,7 @@ private T injectExtension(T instance) {
             }
         }
 
+        // 从配置文件中,加载拓展实现类数组
         Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
         loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
         loadFile(extensionClasses, DUBBO_DIRECTORY);
@@ -581,29 +829,40 @@ private T injectExtension(T instance) {
         return extensionClasses;
     }
 
+    /**
+     * 从一个配置文件中,加载拓展实现类数组。
+     *
+     * @param extensionClasses 拓展类名数组
+     * @param dir 文件名
+     */
     private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
+        // 完整的文件名
         String fileName = dir + type.getName();
         try {
             Enumeration<java.net.URL> urls;
+            // 获得文件名对应的所有文件数组
             ClassLoader classLoader = findClassLoader();
             if (classLoader != null) {
                 urls = classLoader.getResources(fileName);
             } else {
                 urls = ClassLoader.getSystemResources(fileName);
             }
+            // 遍历文件数组
             if (urls != null) {
                 while (urls.hasMoreElements()) {
                     java.net.URL url = urls.nextElement();
                     try {
                         BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
                         try {
-                            String line = null;
+                            String line;
                             while ((line = reader.readLine()) != null) {
+                                // 跳过当前被注释掉的情况,例如 #spring=xxxxxxxxx
                                 final int ci = line.indexOf('#');
                                 if (ci >= 0) line = line.substring(0, ci);
                                 line = line.trim();
                                 if (line.length() > 0) {
                                     try {
+                                        // 拆分,key=value 的配置格式
                                         String name = null;
                                         int i = line.indexOf('=');
                                         if (i > 0) {
@@ -611,12 +870,14 @@ private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
                                             line = line.substring(i + 1).trim();
                                         }
                                         if (line.length() > 0) {
+                                            // 判断拓展实现,是否实现拓展接口
                                             Class<?> clazz = Class.forName(line, true, classLoader);
                                             if (!type.isAssignableFrom(clazz)) {
                                                 throw new IllegalStateException("Error when load extension class(interface: " +
                                                         type + ", class line: " + clazz.getName() + "), class "
                                                         + clazz.getName() + "is not subtype of interface.");
                                             }
+                                            // 缓存自适应拓展对象的类到 `cachedAdaptiveClass`
                                             if (clazz.isAnnotationPresent(Adaptive.class)) {
                                                 if (cachedAdaptiveClass == null) {
                                                     cachedAdaptiveClass = clazz;
@@ -626,6 +887,7 @@ private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
                                                             + ", " + clazz.getClass().getName());
                                                 }
                                             } else {
+                                                // 缓存拓展 Wrapper 实现类到 `cachedWrapperClasses`
                                                 try {
                                                     clazz.getConstructor(type);
                                                     Set<Class<?>> wrappers = cachedWrapperClasses;
@@ -634,8 +896,10 @@ private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
                                                         wrappers = cachedWrapperClasses;
                                                     }
                                                     wrappers.add(clazz);
+                                                // 缓存拓展实现类到 `extensionClasses`
                                                 } catch (NoSuchMethodException e) {
                                                     clazz.getConstructor();
+                                                    // 未配置拓展名,自动生成。例如,DemoFilter 为 demo 。主要用于兼容 Java SPI 的配置。
                                                     if (name == null || name.length() == 0) {
                                                         name = findAnnotationName(clazz);
                                                         if (name == null || name.length() == 0) {
@@ -647,16 +911,20 @@ private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
                                                             }
                                                         }
                                                     }
+                                                    // 获得拓展名,可以是数组,有多个拓展名。
                                                     String[] names = NAME_SEPARATOR.split(name);
                                                     if (names != null && names.length > 0) {
+                                                        // 缓存 @Activate 到 `cachedActivates` 。
                                                         Activate activate = clazz.getAnnotation(Activate.class);
                                                         if (activate != null) {
                                                             cachedActivates.put(names[0], activate);
                                                         }
                                                         for (String n : names) {
+                                                            // 缓存到 `cachedNames`
                                                             if (!cachedNames.containsKey(clazz)) {
                                                                 cachedNames.put(clazz, n);
                                                             }
+                                                            // 缓存拓展实现类到 `extensionClasses`
                                                             Class<?> c = extensionClasses.get(n);
                                                             if (c == null) {
                                                                 extensionClasses.put(n, clazz);
@@ -669,6 +937,7 @@ private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
                                             }
                                         }
                                     } catch (Throwable t) {
+                                        // 发生异常,记录到异常集合
                                         IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
                                         exceptions.put(line, e);
                                     }
@@ -702,6 +971,11 @@ private String findAnnotationName(Class<?> clazz) {
         return extension.value();
     }
 
+    /**
+     * 创建自适应拓展对象
+     *
+     * @return 拓展对象
+     */
     @SuppressWarnings("unchecked")
     private T createAdaptiveExtension() {
         try {
@@ -711,6 +985,9 @@ private T createAdaptiveExtension() {
         }
     }
 
+    /**
+     * @return 自适应拓展类
+     */
     private Class<?> getAdaptiveExtensionClass() {
         getExtensionClasses();
         if (cachedAdaptiveClass != null) {
@@ -719,15 +996,28 @@ private T createAdaptiveExtension() {
         return cachedAdaptiveClass = createAdaptiveExtensionClass();
     }
 
+    /**
+     * 自动生成自适应拓展的代码实现,并编译后返回该类。
+     *
+     * @return 类
+     */
     private Class<?> createAdaptiveExtensionClass() {
+        // 自动生成自适应拓展的代码实现的字符串
         String code = createAdaptiveExtensionClassCode();
+        // 编译代码,并返回该类
         ClassLoader classLoader = findClassLoader();
         com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
         return compiler.compile(code, classLoader);
     }
 
+    /**
+     * 自动生成自适应拓展的代码实现的字符串
+     *
+     * @return 代码字符串
+     */
     private String createAdaptiveExtensionClassCode() {
         StringBuilder codeBuidler = new StringBuilder();
+        // 遍历方法数组,判断有 @Adaptive 注解
         Method[] methods = type.getMethods();
         boolean hasAdaptiveAnnotation = false;
         for (Method m : methods) {
@@ -737,25 +1027,32 @@ private String createAdaptiveExtensionClassCode() {
             }
         }
         // no need to generate adaptive class since there's no adaptive method found.
+        // 完全没有Adaptive方法,则不需要生成Adaptive类
         if (!hasAdaptiveAnnotation)
             throw new IllegalStateException("No adaptive method on extension " + type.getName() + ", refuse to create the adaptive class!");
 
+        // 生成代码:package 和 import
         codeBuidler.append("package " + type.getPackage().getName() + ";");
         codeBuidler.append("\nimport " + ExtensionLoader.class.getName() + ";");
+        // 生成代码:类名
         codeBuidler.append("\npublic class " + type.getSimpleName() + "$Adaptive" + " implements " + type.getCanonicalName() + " {");
 
+        // 循环方法
         for (Method method : methods) {
-            Class<?> rt = method.getReturnType();
-            Class<?>[] pts = method.getParameterTypes();
-            Class<?>[] ets = method.getExceptionTypes();
+            Class<?> rt = method.getReturnType(); // 返回类型
+            Class<?>[] pts = method.getParameterTypes(); // 参数类型数组
+            Class<?>[] ets = method.getExceptionTypes(); // 异常类型数组
 
             Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
-            StringBuilder code = new StringBuilder(512);
+            StringBuilder code = new StringBuilder(512); // 方法体的代码
+            // 非 @Adaptive 注解,生成代码:生成的方法为直接抛出异常。因为,非自适应的接口不应该被调用。
             if (adaptiveAnnotation == null) {
                 code.append("throw new UnsupportedOperationException(\"method ")
                         .append(method.toString()).append(" of interface ")
                         .append(type.getName()).append(" is not adaptive method!\");");
+            // @Adaptive 注解,生成方法体的代码
             } else {
+                // 寻找 Dubbo URL 参数的位置
                 int urlTypeIndex = -1;
                 for (int i = 0; i < pts.length; ++i) {
                     if (pts[i].equals(URL.class)) {
@@ -764,6 +1061,7 @@ private String createAdaptiveExtensionClassCode() {
                     }
                 }
                 // found parameter in URL type
+                // 有类型为URL的参数,生成代码:生成校验 URL 非空的代码
                 if (urlTypeIndex != -1) {
                     // Null Point check
                     String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"url == null\");",
@@ -774,10 +1072,12 @@ private String createAdaptiveExtensionClassCode() {
                     code.append(s);
                 }
                 // did not find parameter in URL type
+                // 参数没有URL类型
                 else {
                     String attribMethod = null;
 
                     // find URL getter method
+                    // 找到参数的URL属性 。例如,Invoker 有 `#getURL()` 方法。
                     LBL_PTS:
                     for (int i = 0; i < pts.length; ++i) {
                         Method[] ms = pts[i].getMethods();
@@ -787,18 +1087,20 @@ private String createAdaptiveExtensionClassCode() {
                                     && Modifier.isPublic(m.getModifiers())
                                     && !Modifier.isStatic(m.getModifiers())
                                     && m.getParameterTypes().length == 0
-                                    && m.getReturnType() == URL.class) {
+                                    && m.getReturnType() == URL.class) { // pubic && getting 方法
                                 urlTypeIndex = i;
                                 attribMethod = name;
                                 break LBL_PTS;
                             }
                         }
                     }
+                    // 未找到,抛出异常。
                     if (attribMethod == null) {
                         throw new IllegalStateException("fail to create adaptive class for interface " + type.getName()
                                 + ": not found url parameter or url attribute in parameters of method " + method.getName());
                     }
 
+                    // 生成代码:校验 URL 非空
                     // Null point check
                     String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"%s argument == null\");",
                             urlTypeIndex, pts[urlTypeIndex].getName());
@@ -807,12 +1109,14 @@ private String createAdaptiveExtensionClassCode() {
                             urlTypeIndex, attribMethod, pts[urlTypeIndex].getName(), attribMethod);
                     code.append(s);
 
+                    // 生成 `URL url = arg%d.%s();` 的代码
                     s = String.format("%s url = arg%d.%s();", URL.class.getName(), urlTypeIndex, attribMethod);
                     code.append(s);
                 }
 
                 String[] value = adaptiveAnnotation.value();
                 // value is not set, use the value generated from class name as the key
+                // 没有设置Key,则使用“扩展点接口名的点分隔 作为Key
                 if (value.length == 0) {
                     char[] charArray = type.getSimpleName().toCharArray();
                     StringBuilder sb = new StringBuilder(128);
@@ -829,35 +1133,45 @@ private String createAdaptiveExtensionClassCode() {
                     value = new String[]{sb.toString()};
                 }
 
+                // 判断是否有 Invocation 参数
                 boolean hasInvocation = false;
                 for (int i = 0; i < pts.length; ++i) {
                     if (pts[i].getName().equals("com.alibaba.dubbo.rpc.Invocation")) {
+                        // 生成代码:校验 Invocation 非空
                         // Null Point check
                         String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"invocation == null\");", i);
                         code.append(s);
+
+                        // 生成代码:获得方法名
                         s = String.format("\nString methodName = arg%d.getMethodName();", i);
                         code.append(s);
+
+                        // 标记有 Invocation 参数
                         hasInvocation = true;
                         break;
                     }
                 }
 
+                // 默认拓展名
                 String defaultExtName = cachedDefaultName;
+                // 获得最终拓展名的代码字符串,例如:
+                // 【简单】1. url.getParameter("proxy", "javassist")
+                // 【复杂】2. url.getParameter(key1, url.getParameter(key2, defaultExtName))
                 String getNameCode = null;
-                for (int i = value.length - 1; i >= 0; --i) {
+                for (int i = value.length - 1; i >= 0; --i) { // 倒序的原因,因为是顺序获取参数,参见【复杂】2. 的例子
                     if (i == value.length - 1) {
                         if (null != defaultExtName) {
                             if (!"protocol".equals(value[i]))
-                                if (hasInvocation)
+                                if (hasInvocation) // 当【有】 Invocation 参数时,使用 `URL#getMethodParameter()` 方法。
                                     getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
-                                else
+                                else // 当【非】 Invocation 参数时,使用 `URL#getParameter()` 方法。
                                     getNameCode = String.format("url.getParameter(\"%s\", \"%s\")", value[i], defaultExtName);
-                            else
+                            else // 当属性名是 "protocol" ,使用 `URL#getProtocl()` 方法获取。
                                 getNameCode = String.format("( url.getProtocol() == null ? \"%s\" : url.getProtocol() )", defaultExtName);
                         } else {
                             if (!"protocol".equals(value[i]))
                                 if (hasInvocation)
-                                    getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
+                                    getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName); // 此处的 defaultExtName ,可以去掉的。
                                 else
                                     getNameCode = String.format("url.getParameter(\"%s\")", value[i]);
                             else
@@ -873,6 +1187,8 @@ private String createAdaptiveExtensionClassCode() {
                             getNameCode = String.format("url.getProtocol() == null ? (%s) : url.getProtocol()", getNameCode);
                     }
                 }
+
+                // 生成代码:获取参数的代码。例如:String extName = url.getParameter("proxy", "javassist");
                 code.append("\nString extName = ").append(getNameCode).append(";");
                 // check extName == null?
                 String s = String.format("\nif(extName == null) " +
@@ -880,6 +1196,9 @@ private String createAdaptiveExtensionClassCode() {
                         type.getName(), Arrays.toString(value));
                 code.append(s);
 
+                // 生成代码:拓展对象,调用方法。例如
+                // `com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class)
+                //                                                                                                           .getExtension(extName);` 。
                 s = String.format("\n%s extension = (%<s)%s.getExtensionLoader(%s.class).getExtension(extName);",
                         type.getName(), ExtensionLoader.class.getSimpleName(), type.getName());
                 code.append(s);
@@ -899,6 +1218,7 @@ private String createAdaptiveExtensionClassCode() {
                 code.append(");");
             }
 
+            // 生成方法
             codeBuidler.append("\npublic " + rt.getCanonicalName() + " " + method.getName() + "(");
             for (int i = 0; i < pts.length; i++) {
                 if (i > 0) {
@@ -910,7 +1230,7 @@ private String createAdaptiveExtensionClassCode() {
             }
             codeBuidler.append(")");
             if (ets.length > 0) {
-                codeBuidler.append(" throws ");
+                codeBuidler.append(" throws ");  // 异常
                 for (int i = 0; i < ets.length; i++) {
                     if (i > 0) {
                         codeBuidler.append(", ");
@@ -922,7 +1242,11 @@ private String createAdaptiveExtensionClassCode() {
             codeBuidler.append(code.toString());
             codeBuidler.append("\n}");
         }
+
+        // 生成类末尾的 `}`
         codeBuidler.append("\n}");
+
+        // 调试,打印生成的代码
         if (logger.isDebugEnabled()) {
             logger.debug(codeBuidler.toString());
         }
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/SPI.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/SPI.java
index 7e7c5437ce..57431e6064 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/SPI.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/SPI.java
@@ -51,6 +51,32 @@
  * instead of reporting which extract extension implementation fails and the extract reason.
  * </p>
  */
+
+/**
+ * 扩展点接口的标识。
+ * 扩展点声明配置文件,格式修改。
+ * 以Protocol示例,配置文件META-INF/dubbo/com.xxx.Protocol内容:
+ * 由
+ *      com.foo.XxxProtocol
+ *      com.foo.YyyProtocol
+ * 改成使用KV格式
+ *      xxx=com.foo.XxxProtocol
+ *      yyy=com.foo.YyyProtocol
+ *
+ * 原因:
+ * 当扩展点的static字段或方法签名上引用了三方库,
+ * 如果三方库不存在,会导致类初始化失败,
+ * Extension标识Dubbo就拿不到了,异常信息就和配置对应不起来。
+ *
+ * 比如:
+ * Extension("mina")加载失败,
+ * 当用户配置使用mina时,就会报找不到扩展点,
+ * 而不是报加载扩展点失败,以及失败原因。
+ *
+ * @author william.liangf
+ * @author ding.lid
+ * @export
+ */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.TYPE})
@@ -58,6 +84,8 @@
 
     /**
      * default extension name
+     *
+     * 默认拓展名
      */
     String value() default "";
 
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/factory/AdaptiveExtensionFactory.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/factory/AdaptiveExtensionFactory.java
index c9235bdddd..d13dff702e 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/factory/AdaptiveExtensionFactory.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/factory/AdaptiveExtensionFactory.java
@@ -30,9 +30,13 @@
 @Adaptive
 public class AdaptiveExtensionFactory implements ExtensionFactory {
 
+    /**
+     * ExtensionFactory 拓展对象集合
+     */
     private final List<ExtensionFactory> factories;
 
     public AdaptiveExtensionFactory() {
+        // 使用 ExtensionLoader 加载拓展对象实现类。
         ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
         List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
         for (String name : loader.getSupportedExtensions()) {
@@ -42,6 +46,7 @@ public AdaptiveExtensionFactory() {
     }
 
     public <T> T getExtension(Class<T> type, String name) {
+        // 遍历工厂数组,直到获得到属性
         for (ExtensionFactory factory : factories) {
             T extension = factory.getExtension(type, name);
             if (extension != null) {
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/factory/SpiExtensionFactory.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/factory/SpiExtensionFactory.java
index 0fc857ed50..ad532f29d2 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/factory/SpiExtensionFactory.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/factory/SpiExtensionFactory.java
@@ -25,9 +25,19 @@
  */
 public class SpiExtensionFactory implements ExtensionFactory {
 
+    /**
+     * 获得拓展对象
+     *
+     * @param type object type. 拓展接口
+     * @param name object name. 拓展名
+     * @param <T> 泛型
+     * @return 拓展对象
+     */
     public <T> T getExtension(Class<T> type, String name) {
-        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
+        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) { // 校验是 @SPI
+            // 加载拓展接口对应的 ExtensionLoader 对象
             ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
+            // 加载拓展对象
             if (!loader.getSupportedExtensions().isEmpty()) {
                 return loader.getAdaptiveExtension();
             }
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/support/ActivateComparator.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/support/ActivateComparator.java
index 809e883d89..eee0f9d0a2 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/support/ActivateComparator.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/extension/support/ActivateComparator.java
@@ -27,9 +27,13 @@
  */
 public class ActivateComparator implements Comparator<Object> {
 
+    /**
+     * 单例
+     */
     public static final Comparator<Object> COMPARATOR = new ActivateComparator();
 
     public int compare(Object o1, Object o2) {
+        // 基本排序
         if (o1 == null && o2 == null) {
             return 0;
         }
@@ -42,13 +46,16 @@ public int compare(Object o1, Object o2) {
         if (o1.equals(o2)) {
             return 0;
         }
+
         Activate a1 = o1.getClass().getAnnotation(Activate.class);
         Activate a2 = o2.getClass().getAnnotation(Activate.class);
-        if ((a1.before().length > 0 || a1.after().length > 0
-                || a2.before().length > 0 || a2.after().length > 0)
-                && o1.getClass().getInterfaces().length > 0
-                && o1.getClass().getInterfaces()[0].isAnnotationPresent(SPI.class)) {
+
+        // 使用注解的 `after` 和 `before` 属性,排序
+        if ((a1.before().length > 0 || a1.after().length > 0 || a2.before().length > 0 || a2.after().length > 0) // (a1 或 a2) 存在 (`after` 或 `before`) 属性。
+                && o1.getClass().getInterfaces().length > 0 && o1.getClass().getInterfaces()[0].isAnnotationPresent(SPI.class)) { // 实现的接口,有 @SPI 注解。
+            // 获得拓展加载器
             ExtensionLoader<?> extensionLoader = ExtensionLoader.getExtensionLoader(o1.getClass().getInterfaces()[0]);
+            // 以 a1 的视角,进行一次比较
             if (a1.before().length > 0 || a1.after().length > 0) {
                 String n2 = extensionLoader.getExtensionName(o2.getClass());
                 for (String before : a1.before()) {
@@ -62,6 +69,7 @@ public int compare(Object o1, Object o2) {
                     }
                 }
             }
+            // 以 a2 的视角,进行一次比较。
             if (a2.before().length > 0 || a2.after().length > 0) {
                 String n1 = extensionLoader.getExtensionName(o1.getClass());
                 for (String before : a2.before()) {
@@ -76,6 +84,8 @@ public int compare(Object o1, Object o2) {
                 }
             }
         }
+
+        // 使用注解的 `order` 属性,排序。
         int n1 = a1 == null ? 0 : a1.order();
         int n2 = a2 == null ? 0 : a2.order();
         // never return 0 even if n1 equals n2, otherwise, o1 and o2 will override each other in collection like HashSet
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/io/UnsafeByteArrayInputStream.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/io/UnsafeByteArrayInputStream.java
index 556c76f203..6523935bf5 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/io/UnsafeByteArrayInputStream.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/io/UnsafeByteArrayInputStream.java
@@ -23,6 +23,7 @@
  * UnsafeByteArrayInputStrem.
  */
 public class UnsafeByteArrayInputStream extends InputStream {
+
     protected byte mData[];
 
     protected int mPosition, mLimit, mMark = 0;
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/logger/Logger.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/logger/Logger.java
index ea3949091e..3de59fb7c1 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/logger/Logger.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/logger/Logger.java
@@ -28,14 +28,14 @@
      *
      * @param msg log this message
      */
-    public void trace(String msg);
+    void trace(String msg);
 
     /**
      * Logs an error with trace log level.
      *
      * @param e log this cause
      */
-    public void trace(Throwable e);
+    void trace(Throwable e);
 
     /**
      * Logs an error with trace log level.
@@ -43,21 +43,21 @@
      * @param msg log this message
      * @param e   log this cause
      */
-    public void trace(String msg, Throwable e);
+    void trace(String msg, Throwable e);
 
     /**
      * Logs a message with debug log level.
      *
      * @param msg log this message
      */
-    public void debug(String msg);
+    void debug(String msg);
 
     /**
      * Logs an error with debug log level.
      *
      * @param e log this cause
      */
-    public void debug(Throwable e);
+    void debug(Throwable e);
 
     /**
      * Logs an error with debug log level.
@@ -65,21 +65,21 @@
      * @param msg log this message
      * @param e   log this cause
      */
-    public void debug(String msg, Throwable e);
+    void debug(String msg, Throwable e);
 
     /**
      * Logs a message with info log level.
      *
      * @param msg log this message
      */
-    public void info(String msg);
+    void info(String msg);
 
     /**
      * Logs an error with info log level.
      *
      * @param e log this cause
      */
-    public void info(Throwable e);
+    void info(Throwable e);
 
     /**
      * Logs an error with info log level.
@@ -87,21 +87,21 @@
      * @param msg log this message
      * @param e   log this cause
      */
-    public void info(String msg, Throwable e);
+    void info(String msg, Throwable e);
 
     /**
      * Logs a message with warn log level.
      *
      * @param msg log this message
      */
-    public void warn(String msg);
+    void warn(String msg);
 
     /**
      * Logs a message with warn log level.
      *
      * @param e log this message
      */
-    public void warn(Throwable e);
+    void warn(Throwable e);
 
     /**
      * Logs a message with warn log level.
@@ -109,21 +109,21 @@
      * @param msg log this message
      * @param e   log this cause
      */
-    public void warn(String msg, Throwable e);
+    void warn(String msg, Throwable e);
 
     /**
      * Logs a message with error log level.
      *
      * @param msg log this message
      */
-    public void error(String msg);
+    void error(String msg);
 
     /**
      * Logs an error with error log level.
      *
      * @param e log this cause
      */
-    public void error(Throwable e);
+    void error(Throwable e);
 
     /**
      * Logs an error with error log level.
@@ -131,41 +131,41 @@
      * @param msg log this message
      * @param e   log this cause
      */
-    public void error(String msg, Throwable e);
+    void error(String msg, Throwable e);
 
     /**
      * Is trace logging currently enabled?
      *
      * @return true if trace is enabled
      */
-    public boolean isTraceEnabled();
+    boolean isTraceEnabled();
 
     /**
      * Is debug logging currently enabled?
      *
      * @return true if debug is enabled
      */
-    public boolean isDebugEnabled();
+    boolean isDebugEnabled();
 
     /**
      * Is info logging currently enabled?
      *
      * @return true if info is enabled
      */
-    public boolean isInfoEnabled();
+    boolean isInfoEnabled();
 
     /**
      * Is warn logging currently enabled?
      *
      * @return true if warn is enabled
      */
-    public boolean isWarnEnabled();
+    boolean isWarnEnabled();
 
     /**
      * Is error logging currently enabled?
      *
      * @return true if error is enabled
      */
-    public boolean isErrorEnabled();
+    boolean isErrorEnabled();
 
 }
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/store/DataStore.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/store/DataStore.java
index a6ac2a4dd2..ffe0084b09 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/store/DataStore.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/store/DataStore.java
@@ -21,6 +21,9 @@
 
 import java.util.Map;
 
+/**
+ * 数据存储接口
+ */
 @SPI("simple")
 public interface DataStore {
 
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/store/support/SimpleDataStore.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/store/support/SimpleDataStore.java
index 69c38d1ad6..346b9363bf 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/store/support/SimpleDataStore.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/store/support/SimpleDataStore.java
@@ -24,11 +24,13 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+/**
+ * 基于内存的数据存储实现
+ */
 public class SimpleDataStore implements DataStore {
 
     // <component name or id, <data-name, data-value>>
-    private ConcurrentMap<String, ConcurrentMap<String, Object>> data =
-            new ConcurrentHashMap<String, ConcurrentMap<String, Object>>();
+    private ConcurrentMap<String, ConcurrentMap<String, Object>> data = new ConcurrentHashMap<String, ConcurrentMap<String, Object>>();
 
     public Map<String, Object> get(String componentName) {
         ConcurrentMap<String, Object> value = data.get(componentName);
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/ThreadPool.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/ThreadPool.java
index 466b1db0de..9752908362 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/ThreadPool.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/ThreadPool.java
@@ -25,6 +25,8 @@
 
 /**
  * ThreadPool
+ *
+ * 线程池接口
  */
 @SPI("fixed")
 public interface ThreadPool {
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/AbortPolicyWithReport.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/AbortPolicyWithReport.java
index 9246d96a8f..438274a89a 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/AbortPolicyWithReport.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/AbortPolicyWithReport.java
@@ -35,17 +35,28 @@
 /**
  * Abort Policy.
  * Log warn info when abort.
+ *
+ * 拒绝策略实现类。打印 JStack ,分析线程状态。
  */
 public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
 
     protected static final Logger logger = LoggerFactory.getLogger(AbortPolicyWithReport.class);
 
+    /**
+     * 线程名
+     */
     private final String threadName;
-
+    /**
+     * URL 对象
+     */
     private final URL url;
-
+    /**
+     * 最后打印时间
+     */
     private static volatile long lastPrintTime = 0;
-
+    /**
+     * 信号量,大小为 1 。
+     */
     private static Semaphore guard = new Semaphore(1);
 
     public AbortPolicyWithReport(String threadName, URL url) {
@@ -55,6 +66,7 @@ public AbortPolicyWithReport(String threadName, URL url) {
 
     @Override
     public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
+        // 打印告警日志
         String msg = String.format("Thread pool is EXHAUSTED!" +
                         " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d)," +
                         " Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s), in %s://%s:%d!",
@@ -62,47 +74,58 @@ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                 e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminating(),
                 url.getProtocol(), url.getIp(), url.getPort());
         logger.warn(msg);
+        // 打印 JStack ,分析线程状态。
         dumpJStack();
+        // 抛出 RejectedExecutionException 异常
         throw new RejectedExecutionException(msg);
     }
 
+    /**
+     * 打印 JStack
+     */
     private void dumpJStack() {
         long now = System.currentTimeMillis();
 
-        //dump every 10 minutes
+        // 每 10 分钟,打印一次。
+        // dump every 10 minutes
         if (now - lastPrintTime < 10 * 60 * 1000) {
             return;
         }
 
+        // 获得信号量
         if (!guard.tryAcquire()) {
             return;
         }
 
+        // 创建线程池,后台执行打印 JStack
         Executors.newSingleThreadExecutor().execute(new Runnable() {
             @Override
             public void run() {
-                String dumpPath = url.getParameter(Constants.DUMP_DIRECTORY, System.getProperty("user.home"));
-
-                SimpleDateFormat sdf;
 
+                // 获得系统
                 String OS = System.getProperty("os.name").toLowerCase();
-
+                // 获得路径
+                String dumpPath = url.getParameter(Constants.DUMP_DIRECTORY, System.getProperty("user.home"));
+                SimpleDateFormat sdf;
                 // window system don't support ":" in file name
                 if(OS.contains("win")){
                     sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
                 }else {
                     sdf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
                 }
-
                 String dateStr = sdf.format(new Date());
+                // 获得输出流
                 FileOutputStream jstackStream = null;
                 try {
                     jstackStream = new FileOutputStream(new File(dumpPath, "Dubbo_JStack.log" + "." + dateStr));
+                    // 打印 JStack
                     JVMUtil.jstack(jstackStream);
                 } catch (Throwable t) {
                     logger.error("dump jstack error", t);
                 } finally {
+                    // 释放信号量
                     guard.release();
+                    // 释放输出流
                     if (jstackStream != null) {
                         try {
                             jstackStream.flush();
@@ -111,7 +134,7 @@ public void run() {
                         }
                     }
                 }
-
+                // 记录最后打印时间
                 lastPrintTime = System.currentTimeMillis();
             }
         });
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/cached/CachedThreadPool.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/cached/CachedThreadPool.java
index f63bda0c59..f34c2ca01a 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/cached/CachedThreadPool.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/cached/CachedThreadPool.java
@@ -32,16 +32,25 @@
  * This thread pool is self-tuned. Thread will be recycled after idle for one minute, and new thread will be created for
  * the upcoming request.
  *
+ * 缓存线程池,空闲一分钟自动删除,需要时重建。
+ *
  * @see java.util.concurrent.Executors#newCachedThreadPool()
  */
 public class CachedThreadPool implements ThreadPool {
 
+    @Override
     public Executor getExecutor(URL url) {
+        // 线程名
         String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
+        // 核心线程数
         int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS);
+        // 最大线程数
         int threads = url.getParameter(Constants.THREADS_KEY, Integer.MAX_VALUE);
+        // 队列数
         int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);
+        // 线程存活时长
         int alive = url.getParameter(Constants.ALIVE_KEY, Constants.DEFAULT_ALIVE);
+        // 创建执行器
         return new ThreadPoolExecutor(cores, threads, alive, TimeUnit.MILLISECONDS,
                 queues == 0 ? new SynchronousQueue<Runnable>() :
                         (queues < 0 ? new LinkedBlockingQueue<Runnable>()
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/fixed/FixedThreadPool.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/fixed/FixedThreadPool.java
index c8fe922dfa..c294960cb6 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/fixed/FixedThreadPool.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/fixed/FixedThreadPool.java
@@ -31,14 +31,21 @@
 /**
  * Creates a thread pool that reuses a fixed number of threads
  *
+ * 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)
+ *
  * @see java.util.concurrent.Executors#newFixedThreadPool(int)
  */
 public class FixedThreadPool implements ThreadPool {
 
+    @Override
     public Executor getExecutor(URL url) {
+        // 线程名
         String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
+        // 线程数
         int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);
+        // 队列数
         int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);
+        // 创建执行器
         return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS,
                 queues == 0 ? new SynchronousQueue<Runnable>() :
                         (queues < 0 ? new LinkedBlockingQueue<Runnable>()
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/limited/LimitedThreadPool.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/limited/LimitedThreadPool.java
index d1d9156b95..aa07673c48 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/limited/LimitedThreadPool.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadpool/support/limited/LimitedThreadPool.java
@@ -32,14 +32,22 @@
 /**
  * Creates a thread pool that creates new threads as needed until limits reaches. This thread pool will not shrink
  * automatically.
+ *
+ * 可伸缩线程池,但池中的线程数只会增长不会收缩。只增长不收缩的目的是为了避免收缩时突然来了大流量引起的性能问题。
  */
 public class LimitedThreadPool implements ThreadPool {
 
+    @Override
     public Executor getExecutor(URL url) {
+        // 线程名
         String name = url.getParameter(Constants.THREAD_NAME_KEY, Constants.DEFAULT_THREAD_NAME);
+        // 核心线程数
         int cores = url.getParameter(Constants.CORE_THREADS_KEY, Constants.DEFAULT_CORE_THREADS);
+        // 最大线程数
         int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);
+        // 队列数
         int queues = url.getParameter(Constants.QUEUES_KEY, Constants.DEFAULT_QUEUES);
+        // 创建执行器
         return new ThreadPoolExecutor(cores, threads, Long.MAX_VALUE, TimeUnit.MILLISECONDS,
                 queues == 0 ? new SynchronousQueue<Runnable>() :
                         (queues < 0 ? new LinkedBlockingQueue<Runnable>()
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ClassHelper.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ClassHelper.java
index f6ac8d3bb1..b928738fc8 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ClassHelper.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ClassHelper.java
@@ -76,6 +76,10 @@
         return forName(name, caller.getClassLoader());
     }
 
+    /**
+     * @param caller 调用类
+     * @return 调用类的类加载器
+     */
     public static ClassLoader getCallerClassLoader(Class<?> caller) {
         return caller.getClassLoader();
     }
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ExecutorUtil.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ExecutorUtil.java
index eea7483819..5b8be8d0cd 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ExecutorUtil.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/ExecutorUtil.java
@@ -122,4 +122,5 @@ public static URL setThreadName(URL url, String defaultName) {
         url = url.addParameter(Constants.THREAD_NAME_KEY, name);
         return url;
     }
+
 }
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/Holder.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/Holder.java
index 810b83b1d0..ce19825b86 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/Holder.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/Holder.java
@@ -21,6 +21,9 @@
  */
 public class Holder<T> {
 
+    /**
+     * 值
+     */
     private volatile T value;
 
     public void set(T value) {
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/JVMUtil.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/JVMUtil.java
index 49c726c6f9..bb3af3b1ad 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/JVMUtil.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/JVMUtil.java
@@ -23,9 +23,14 @@
 import java.lang.management.ThreadInfo;
 import java.lang.management.ThreadMXBean;
 
+/**
+ * JVM 工具类
+ */
 public class JVMUtil {
+
     public static void jstack(OutputStream stream) throws Exception {
         ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
+        // 循环每个线程
         for (ThreadInfo threadInfo : threadMxBean.dumpAllThreads(true, true)) {
             stream.write(getThreadDumpString(threadInfo).getBytes());
         }
@@ -55,7 +60,7 @@ private static String getThreadDumpString(ThreadInfo threadInfo) {
         MonitorInfo[] lockedMonitors = threadInfo.getLockedMonitors();
         for (; i < stackTrace.length && i < 32; i++) {
             StackTraceElement ste = stackTrace[i];
-            sb.append("\tat " + ste.toString());
+            sb.append("\tat ").append(ste.toString());
             sb.append('\n');
             if (i == 0 && threadInfo.getLockInfo() != null) {
                 Thread.State ts = threadInfo.getThreadState();
@@ -100,4 +105,5 @@ private static String getThreadDumpString(ThreadInfo threadInfo) {
         sb.append('\n');
         return sb.toString();
     }
+
 }
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/NetUtils.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/NetUtils.java
index 5295831632..6fa787b9de 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/NetUtils.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/NetUtils.java
@@ -52,6 +52,11 @@
     private static final Map<String, String> hostNameCache = new LRUCache<String, String>(1000);
     private static volatile InetAddress LOCAL_ADDRESS = null;
 
+    /**
+     * 随机端口,从 30000 + 开始
+     *
+     * @return 端口
+     */
     public static int getRandomPort() {
         return RND_PORT_START + RANDOM.nextInt(RND_PORT_RANGE);
     }
@@ -63,6 +68,7 @@ public static int getAvailablePort() {
             ss.bind(null);
             return ss.getLocalPort();
         } catch (IOException e) {
+            // 发生异常,随机获得端口
             return getRandomPort();
         } finally {
             if (ss != null) {
@@ -74,10 +80,18 @@ public static int getAvailablePort() {
         }
     }
 
+    /**
+     * 获得本地可用端口
+     *
+     * @param port 目标开始端口
+     * @return 成功的本地可用端口
+     */
     public static int getAvailablePort(int port) {
+        // 获得一个本地端口。
         if (port <= 0) {
             return getAvailablePort();
         }
+        // 从 port 开始,顺序使用端口,直到成功
         for (int i = port; i < MAX_PORT; i++) {
             ServerSocket ss = null;
             try {
@@ -115,6 +129,14 @@ public static boolean isAnyHost(String host) {
         return "0.0.0.0".equals(host);
     }
 
+    /**
+     * 判断是否为非法的本地 Host
+     *
+     * 空 || localhost || 0.0.0.0 || 127.x.x.x
+     *
+     * @param host host
+     * @return 是否
+     */
     public static boolean isInvalidLocalHost(String host) {
         return host == null
                 || host.length() == 0
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/StringUtils.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/StringUtils.java
index faf349f801..26d9b8c7e5 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/StringUtils.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/StringUtils.java
@@ -349,13 +349,25 @@ public static String getQueryStringValue(String qs, String key) {
         return parseKeyValuePair(qs, "\\&");
     }
 
+    /**
+     * 获得服务键
+     *
+     * 格式为 ${group}/${interface}:${version}
+     * 例如,com.alibaba.dubbo.demo.DemoService
+     *
+     * @param ps 参数集合 {@link com.alibaba.dubbo.common.URL#parameter}
+     * @return 服务键
+     */
     public static String getServiceKey(Map<String, String> ps) {
         StringBuilder buf = new StringBuilder();
+        // group
         String group = ps.get(Constants.GROUP_KEY);
         if (group != null && group.length() > 0) {
             buf.append(group).append("/");
         }
+        // interface
         buf.append(ps.get(Constants.INTERFACE_KEY));
+        // version
         String version = ps.get(Constants.VERSION_KEY);
         if (version != null && version.length() > 0) {
             buf.append(":").append(version);
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/UrlUtils.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/UrlUtils.java
index 9ba130081f..0042e66b3b 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/UrlUtils.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/UrlUtils.java
@@ -27,15 +27,30 @@
 
 public class UrlUtils {
 
+    /**
+     * 解析单个 URL ,将 `defaults` 里的参数,合并到 `address` 中。
+     *
+     * 合并的逻辑如下:
+     *
+     * 我们可以把 `address` 认为是 url ;`defaults` 认为是 defaultURL 。
+     * 若 url 有不存在的属性时,从 defaultURL 获得对应的属性,设置到 url 中。
+     *
+     * @param address 地址
+     * @param defaults 默认参数集合
+     * @return URL
+     */
     public static URL parseURL(String address, Map<String, String> defaults) {
         if (address == null || address.length() == 0) {
             return null;
         }
+        // 以 Zookeeper 注册中心,配置集群的例子如下:
+        // 第一种,<dubbo:registry address="zookeeper://10.20.153.10:2181?backup=10.20.153.11:2181,10.20.153.12:2181"/>
+        // 第二种,<dubbo:registry protocol="zookeeper" address="10.20.153.10:2181,10.20.153.11:2181,10.20.153.12:2181"/>
         String url;
-        if (address.indexOf("://") >= 0) {
+        if (address.contains("://")) { // 第一种
             url = address;
-        } else {
-            String[] addresses = Constants.COMMA_SPLIT_PATTERN.split(address);
+        } else { // 第二种
+            String[] addresses = Constants.COMMA_SPLIT_PATTERN.split(address); // 按照 逗号 拆分
             url = addresses[0];
             if (addresses.length > 1) {
                 StringBuilder backup = new StringBuilder();
@@ -48,8 +63,10 @@ public static URL parseURL(String address, Map<String, String> defaults) {
                 url += "?" + Constants.BACKUP_KEY + "=" + backup.toString();
             }
         }
+        // 从 `defaults` 中,获得 "protocol" "username" "password" "host" "port" "path" 到 `defaultXXX` 属性种。
+        // 因为,在 Dubbo URL 中,这几个是独立的属性,不在 `Dubbo.parameters` 属性中。
         String defaultProtocol = defaults == null ? null : defaults.get("protocol");
-        if (defaultProtocol == null || defaultProtocol.length() == 0) {
+        if (defaultProtocol == null || defaultProtocol.length() == 0) { // 如果地址没有协议缺省为 dubbo
             defaultProtocol = "dubbo";
         }
         String defaultUsername = defaults == null ? null : defaults.get("username");
@@ -57,7 +74,7 @@ public static URL parseURL(String address, Map<String, String> defaults) {
         int defaultPort = StringUtils.parseInteger(defaults == null ? null : defaults.get("port"));
         String defaultPath = defaults == null ? null : defaults.get("path");
         Map<String, String> defaultParameters = defaults == null ? null : new HashMap<String, String>(defaults);
-        if (defaultParameters != null) {
+        if (defaultParameters != null) { // 需要移除,因为这几个是独立属性。
             defaultParameters.remove("protocol");
             defaultParameters.remove("username");
             defaultParameters.remove("password");
@@ -65,8 +82,10 @@ public static URL parseURL(String address, Map<String, String> defaults) {
             defaultParameters.remove("port");
             defaultParameters.remove("path");
         }
+        // 创建 Dubbo URL 。
         URL u = URL.valueOf(url);
-        boolean changed = false;
+        // 若 `u` 的属性存在非空的情况下,从 `defaultXXX` 属性,赋值到 `u` 的属性中。
+        boolean changed = false; // 是否改变,即从 `defaultXXX` 属性,赋值到 `u` 的属性中。
         String protocol = u.getProtocol();
         String username = u.getUsername();
         String password = u.getPassword();
@@ -74,7 +93,7 @@ public static URL parseURL(String address, Map<String, String> defaults) {
         int port = u.getPort();
         String path = u.getPath();
         Map<String, String> parameters = new HashMap<String, String>(u.getParameters());
-        if ((protocol == null || protocol.length() == 0) && defaultProtocol != null && defaultProtocol.length() > 0) {
+        if ((protocol == null || protocol.length() == 0) && defaultProtocol.length() > 0) {
             changed = true;
             protocol = defaultProtocol;
         }
@@ -94,7 +113,7 @@ public static URL parseURL(String address, Map<String, String> defaults) {
             if (defaultPort > 0) {
                 changed = true;
                 port = defaultPort;
-            } else {
+            } else { // 如果地址没有端口缺省为9090。FROM http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-registry.html 文档。
                 changed = true;
                 port = 9090;
             }
@@ -118,13 +137,27 @@ public static URL parseURL(String address, Map<String, String> defaults) {
                 }
             }
         }
+        // 若改变,创建新的 Dubbo URL 。
         if (changed) {
             u = new URL(protocol, username, password, host, port, path, parameters);
         }
         return u;
     }
 
+    /**
+     * 解析多个 URL ,将 `defaults` 里的参数,合并到 `address` 中。
+     *
+     * 合并的逻辑如下:
+     *
+     * 我们可以把 `address` 认为是 url ;`defaults` 认为是 defaultURL 。
+     * 若 url 有不存在的属性时,从 defaultURL 获得对应的属性,设置到 url 中。
+     *
+     * @param address 地址
+     * @param defaults 默认参数集合
+     * @return URL
+     */
     public static List<URL> parseURLs(String address, Map<String, String> defaults) {
+        // 拆分注册中心地址,按照逗号或者分号。
         if (address == null || address.length() == 0) {
             return null;
         }
@@ -134,11 +167,13 @@ public static URL parseURL(String address, Map<String, String> defaults) {
         }
         List<URL> registries = new ArrayList<URL>();
         for (String addr : addresses) {
+            // 解析 URL ,将 `defaults` 里的参数,合并到 `addr` 中。
             registries.add(parseURL(addr, defaults));
         }
         return registries;
     }
 
+    // 芋艿,可无视;测试类使用
     public static Map<String, Map<String, String>> convertRegister(Map<String, Map<String, String>> register) {
         Map<String, Map<String, String>> newRegister = new HashMap<String, Map<String, String>>();
         for (Map.Entry<String, Map<String, String>> entry : register.entrySet()) {
@@ -174,6 +209,7 @@ public static URL parseURL(String address, Map<String, String> defaults) {
         return newRegister;
     }
 
+    // 芋艿,可无视;测试类使用
     public static Map<String, String> convertSubscribe(Map<String, String> subscribe) {
         Map<String, String> newSubscribe = new HashMap<String, String>();
         for (Map.Entry<String, String> entry : subscribe.entrySet()) {
@@ -200,6 +236,7 @@ public static URL parseURL(String address, Map<String, String> defaults) {
         return newSubscribe;
     }
 
+    // 芋艿,可无视;测试类使用
     public static Map<String, Map<String, String>> revertRegister(Map<String, Map<String, String>> register) {
         Map<String, Map<String, String>> newRegister = new HashMap<String, Map<String, String>>();
         for (Map.Entry<String, Map<String, String>> entry : register.entrySet()) {
@@ -235,6 +272,7 @@ public static URL parseURL(String address, Map<String, String> defaults) {
         return newRegister;
     }
 
+    // 芋艿,可无视;测试类使用
     public static Map<String, String> revertSubscribe(Map<String, String> subscribe) {
         Map<String, String> newSubscribe = new HashMap<String, String>();
         for (Map.Entry<String, String> entry : subscribe.entrySet()) {
@@ -261,6 +299,7 @@ public static URL parseURL(String address, Map<String, String> defaults) {
         return newSubscribe;
     }
 
+    // 芋艿,可无视;测试类使用
     public static Map<String, Map<String, String>> revertNotify(Map<String, Map<String, String>> notify) {
         if (notify != null && notify.size() > 0) {
             Map<String, Map<String, String>> newNotify = new HashMap<String, Map<String, String>>();
@@ -301,6 +340,7 @@ public static URL parseURL(String address, Map<String, String> defaults) {
         return notify;
     }
 
+    // 芋艿,可无视;测试类使用
     //compatible for dubbo-2.0.0
     public static List<String> revertForbid(List<String> forbid, Set<URL> subscribed) {
         if (forbid != null && !forbid.isEmpty()) {
@@ -322,6 +362,7 @@ public static URL parseURL(String address, Map<String, String> defaults) {
         return forbid;
     }
 
+    // 芋艿,可无视;未调用
     public static URL getEmptyUrl(String service, String category) {
         String group = null;
         String version = null;
@@ -418,13 +459,20 @@ else if (i == 0) {
         }
     }
 
+    /**
+     * 判断服务键是否匹配
+     *
+     * @param pattern 匹配 URL
+     * @param value 被匹配 URL
+     * @return 是否
+     */
     public static boolean isServiceKeyMatch(URL pattern, URL value) {
-        return pattern.getParameter(Constants.INTERFACE_KEY).equals(
-                value.getParameter(Constants.INTERFACE_KEY))
-                && isItemMatch(pattern.getParameter(Constants.GROUP_KEY),
-                value.getParameter(Constants.GROUP_KEY))
-                && isItemMatch(pattern.getParameter(Constants.VERSION_KEY),
-                value.getParameter(Constants.VERSION_KEY));
+                // interface
+        return pattern.getParameter(Constants.INTERFACE_KEY).equals(value.getParameter(Constants.INTERFACE_KEY))
+                // group
+                && isItemMatch(pattern.getParameter(Constants.GROUP_KEY), value.getParameter(Constants.GROUP_KEY))
+                // version
+                && isItemMatch(pattern.getParameter(Constants.VERSION_KEY), value.getParameter(Constants.VERSION_KEY));
     }
 
     /**
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractConfig.java
index 18e15fb87c..a98438c5e0 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractConfig.java
@@ -43,7 +43,11 @@
 public abstract class AbstractConfig implements Serializable {
 
     protected static final Logger logger = LoggerFactory.getLogger(AbstractConfig.class);
+
     private static final long serialVersionUID = 4267533505537413570L;
+
+    // ========== 属性值的格式校验,参见本类的 `#checkXXX` 方法 BEGIN ==========
+
     private static final int MAX_LENGTH = 200;
 
     private static final int MAX_PATH_LENGTH = 200;
@@ -59,7 +63,23 @@
     private static final Pattern PATTERN_NAME_HAS_SYMBOL = Pattern.compile("[:*,/\\-._0-9a-zA-Z]+");
 
     private static final Pattern PATTERN_KEY = Pattern.compile("[*,\\-._0-9a-zA-Z]+");
+
+    // ========== 属性值的格式校验,参见本类的 `#checkXXX` 方法 END ==========
+
+    /**
+     * 新老版本的 properties 的 key 映射
+     *
+     * key:新版本的配置 映射
+     * value:旧版本的配置 映射
+     *
+     * 来自 2012/3/8 下午 5:51 cb1f705 提交
+     * DUBBO-251 增加API覆盖dubbo.properties的测试,以及旧版本配置项测试。
+     */
     private static final Map<String, String> legacyProperties = new HashMap<String, String>();
+    /**
+     * 配置类名的后缀
+     * 例如,ServiceConfig 后缀为 Config;ServiceBean 后缀为 Bean。
+     */
     private static final String[] SUFFIXES = new String[]{"Config", "Bean"};
 
     static {
@@ -73,7 +93,7 @@
         legacyProperties.put("dubbo.service.url", "dubbo.service.address");
     }
 
-    static {
+    static { // TODO 芋艿,注意
         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
             public void run() {
                 if (logger.isInfoEnabled()) {
@@ -84,8 +104,20 @@ public void run() {
         }, "DubboShutdownHook"));
     }
 
+    /**
+     * 配置对象的编号
+     */
     protected String id;
 
+    /**
+     * 将键对应的值转换成目标的值。
+     *
+     * 因为,新老配置可能有一些差异,通过该方法进行转换。
+     *
+     * @param key 键
+     * @param value 值
+     * @return 转换后的值
+     */
     private static String convertLegacyValue(String key, String value) {
         if (value != null && value.length() > 0) {
             if ("dubbo.service.max.retry.providers".equals(key)) {
@@ -97,6 +129,13 @@ private static String convertLegacyValue(String key, String value) {
         return value;
     }
 
+    /**
+     * 读取启动参数变量和 properties 配置到配置对象
+     *
+     * 参见:<a href="https://dubbo.gitbooks.io/dubbo-user-book/configuration/properties.html">属性配置</a>
+     *
+     * @param config 配置对象
+     */
     protected static void appendProperties(AbstractConfig config) {
         if (config == null) {
             return;
@@ -106,26 +145,30 @@ protected static void appendProperties(AbstractConfig config) {
         for (Method method : methods) {
             try {
                 String name = method.getName();
-                if (name.length() > 3 && name.startsWith("set") && Modifier.isPublic(method.getModifiers())
-                        && method.getParameterTypes().length == 1 && isPrimitive(method.getParameterTypes()[0])) {
+                if (name.length() > 3 && name.startsWith("set") && Modifier.isPublic(method.getModifiers()) // 方法是 public 的 setting 方法。
+                        && method.getParameterTypes().length == 1 && isPrimitive(method.getParameterTypes()[0])) { // 方法的唯一参数是基本数据类型
+                    // 获得属性名,例如 `ApplicationConfig#setName(...)` 方法,对应的属性名为 name 。
                     String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), ".");
 
+                    // 【启动参数变量】优先从带有 `Config#id` 的配置中获取,例如:`dubbo.application.demo-provider.name` 。
                     String value = null;
                     if (config.getId() != null && config.getId().length() > 0) {
-                        String pn = prefix + config.getId() + "." + property;
+                        String pn = prefix + config.getId() + "." + property; // 带有 `Config#id`
                         value = System.getProperty(pn);
                         if (!StringUtils.isBlank(value)) {
                             logger.info("Use System Property " + pn + " to config dubbo");
                         }
                     }
+                    // 【启动参数变量】获取不到,其次不带 `Config#id` 的配置中获取,例如:`dubbo.application.name` 。
                     if (value == null || value.length() == 0) {
-                        String pn = prefix + property;
+                        String pn = prefix + property; // // 不带 `Config#id`
                         value = System.getProperty(pn);
                         if (!StringUtils.isBlank(value)) {
                             logger.info("Use System Property " + pn + " to config dubbo");
                         }
                     }
                     if (value == null || value.length() == 0) {
+                        // 覆盖优先级为:启动参数变量 > XML 配置 > properties 配置,因此需要使用 getter 判断 XML 是否已经设置
                         Method getter;
                         try {
                             getter = config.getClass().getMethod("get" + name.substring(3), new Class<?>[0]);
@@ -137,13 +180,16 @@ protected static void appendProperties(AbstractConfig config) {
                             }
                         }
                         if (getter != null) {
-                            if (getter.invoke(config, new Object[0]) == null) {
+                            if (getter.invoke(config, new Object[0]) == null) { // 使用 getter 判断 XML 是否已经设置
+                                // 【properties 配置】优先从带有 `Config#id` 的配置中获取,例如:`dubbo.application.demo-provider.name` 。
                                 if (config.getId() != null && config.getId().length() > 0) {
                                     value = ConfigUtils.getProperty(prefix + config.getId() + "." + property);
                                 }
+                                // 【properties 配置】获取不到,其次不带 `Config#id` 的配置中获取,例如:`dubbo.application.name` 。
                                 if (value == null || value.length() == 0) {
                                     value = ConfigUtils.getProperty(prefix + property);
                                 }
+                                // 【properties 配置】老版本兼容,获取不到,最后不带 `Config#id` 的配置中获取,例如:`dubbo.protocol.name` 。
                                 if (value == null || value.length() == 0) {
                                     String legacyKey = legacyProperties.get(prefix + property);
                                     if (legacyKey != null && legacyKey.length() > 0) {
@@ -154,6 +200,7 @@ protected static void appendProperties(AbstractConfig config) {
                             }
                         }
                     }
+                    // 获取到值,进行反射设置。
                     if (value != null && value.length() > 0) {
                         method.invoke(config, new Object[]{convertPrimitive(method.getParameterTypes()[0], value)});
                     }
@@ -164,6 +211,12 @@ protected static void appendProperties(AbstractConfig config) {
         }
     }
 
+    /**
+     * 获取类名对应的属性标签,例如,ServiceConfig 对应为 service 。
+     *
+     * @param cls 类名
+     * @return 标签
+     */
     private static String getTagName(Class<?> cls) {
         String tag = cls.getSimpleName();
         for (String suffix : SUFFIXES) {
@@ -180,6 +233,13 @@ protected static void appendParameters(Map<String, String> parameters, Object co
         appendParameters(parameters, config, null);
     }
 
+    /**
+     * 将配置对象的属性,添加到参数集合
+     *
+     * @param parameters 参数集合
+     * @param config 配置对象
+     * @param prefix 属性前缀
+     */
     @SuppressWarnings("unchecked")
     protected static void appendParameters(Map<String, String> parameters, Object config, String prefix) {
         if (config == null) {
@@ -193,11 +253,12 @@ protected static void appendParameters(Map<String, String> parameters, Object co
                         && !"getClass".equals(name)
                         && Modifier.isPublic(method.getModifiers())
                         && method.getParameterTypes().length == 0
-                        && isPrimitive(method.getReturnType())) {
+                        && isPrimitive(method.getReturnType())) { // 方法为获取基本类型,public 的 getting 方法。
                     Parameter parameter = method.getAnnotation(Parameter.class);
                     if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {
                         continue;
                     }
+                    // 获得属性名
                     int i = name.startsWith("get") ? 3 : 2;
                     String prop = StringUtils.camelToSplitName(name.substring(i, i + 1).toLowerCase() + name.substring(i + 1), ".");
                     String key;
@@ -206,18 +267,21 @@ protected static void appendParameters(Map<String, String> parameters, Object co
                     } else {
                         key = prop;
                     }
+                    // 获得属性值
                     Object value = method.invoke(config, new Object[0]);
                     String str = String.valueOf(value).trim();
                     if (value != null && str.length() > 0) {
+                        // 转义
                         if (parameter != null && parameter.escaped()) {
                             str = URL.encode(str);
                         }
+                        // 拼接,详细说明参见 `Parameter#append()` 方法的说明。
                         if (parameter != null && parameter.append()) {
-                            String pre = (String) parameters.get(Constants.DEFAULT_KEY + "." + key);
+                            String pre = parameters.get(Constants.DEFAULT_KEY + "." + key); // default. 里获取,适用于 ServiceConfig =》ProviderConfig 、ReferenceConfig =》ConsumerConfig 。
                             if (pre != null && pre.length() > 0) {
                                 str = pre + "," + str;
                             }
-                            pre = (String) parameters.get(key);
+                            pre = parameters.get(key); // 通过 `parameters` 属性配置,例如 `AbstractMethodConfig.parameters` 。
                             if (pre != null && pre.length() > 0) {
                                 str = pre + "," + str;
                             }
@@ -226,13 +290,14 @@ protected static void appendParameters(Map<String, String> parameters, Object co
                             key = prefix + "." + key;
                         }
                         parameters.put(key, str);
+//                        System.out.println("kv:" + key + "\t" + str);
                     } else if (parameter != null && parameter.required()) {
                         throw new IllegalStateException(config.getClass().getSimpleName() + "." + key + " == null");
                     }
                 } else if ("getParameters".equals(name)
                         && Modifier.isPublic(method.getModifiers())
                         && method.getParameterTypes().length == 0
-                        && method.getReturnType() == Map.class) {
+                        && method.getReturnType() == Map.class) { // `#getParameters()` 方法
                     Map<String, String> map = (Map<String, String>) method.invoke(config, new Object[0]);
                     if (map != null && map.size() > 0) {
                         String pre = (prefix != null && prefix.length() > 0 ? prefix + "." : "");
@@ -251,6 +316,13 @@ protected static void appendAttributes(Map<Object, Object> parameters, Object co
         appendAttributes(parameters, config, null);
     }
 
+    /**
+     * 将带有 @Parameter(attribute = true) 配置对象的属性,添加到参数集合
+     *
+     * @param parameters 参数集合
+     * @param config 配置对象
+     * @param prefix 前缀
+     */
     protected static void appendAttributes(Map<Object, Object> parameters, Object config, String prefix) {
         if (config == null) {
             return;
@@ -263,10 +335,11 @@ protected static void appendAttributes(Map<Object, Object> parameters, Object co
                         && !"getClass".equals(name)
                         && Modifier.isPublic(method.getModifiers())
                         && method.getParameterTypes().length == 0
-                        && isPrimitive(method.getReturnType())) {
+                        && isPrimitive(method.getReturnType())) { // 方法为获取基本类型,public 的 getting 方法。
                     Parameter parameter = method.getAnnotation(Parameter.class);
                     if (parameter == null || !parameter.attribute())
                         continue;
+                    // 获得属性名
                     String key;
                     if (parameter != null && parameter.key() != null && parameter.key().length() > 0) {
                         key = parameter.key();
@@ -274,6 +347,7 @@ protected static void appendAttributes(Map<Object, Object> parameters, Object co
                         int i = name.startsWith("get") ? 3 : 2;
                         key = name.substring(i, i + 1).toLowerCase() + name.substring(i + 1);
                     }
+                    // 获得属性值,存在则添加到 `parameters` 集合
                     Object value = method.invoke(config, new Object[0]);
                     if (value != null) {
                         if (prefix != null && prefix.length() > 0) {
@@ -288,6 +362,12 @@ protected static void appendAttributes(Map<Object, Object> parameters, Object co
         }
     }
 
+    /**
+     * 类型是否为基本数据类型。
+     *
+     * @param type 类型
+     * @return 是否
+     */
     private static boolean isPrimitive(Class<?> type) {
         return type.isPrimitive()
                 || type == String.class
@@ -302,6 +382,13 @@ private static boolean isPrimitive(Class<?> type) {
                 || type == Object.class;
     }
 
+    /**
+     * 将字符串转换成目标的基本数据类型的值
+     *
+     * @param type 目标的基本数据类型
+     * @param value 字符串
+     * @return 值
+     */
     private static Object convertPrimitive(Class<?> type, String value) {
         if (type == char.class || type == Character.class) {
             return value.length() > 0 ? value.charAt(0) : '\0';
@@ -453,6 +540,11 @@ protected void appendAnnotation(Class<?> annotationClass, Object annotation) {
         }
     }
 
+    /**
+     * 拼接成 XML 配置对象的字符串
+     *
+     * @return XML
+     */
     @Override
     public String toString() {
         try {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java
index acb22a4fd0..7cc6fda79a 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java
@@ -44,23 +44,40 @@
 /**
  * AbstractDefaultConfig
  *
+ * 抽象接口配置类
+ *
  * @export
  */
 public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
 
     private static final long serialVersionUID = -1559314110797223229L;
 
-    // local impl class name for the service interface
-    protected String local;
-
-    // local stub class name for the service interface
-    protected String stub;
+    /**
+     * local impl class name for the service interface
+     * 服务接口客户端本地代理类名,用于在客户端执行本地逻辑,如本地缓存等。
+     *
+     * 该本地代理类的构造函数必须允许传入远程代理对象,构造函数如:public XxxServiceLocal(XxxService xxxService)
+     *
+     * 设为 true,表示使用缺省代理类名,即:接口名 + Local 后缀
+     */
+    protected String local; // TODO 芋艿
+    /**
+     * local stub class name for the service interface
+     * 服务接口客户端本地代理类名,用于在客户端执行本地逻辑,如本地缓存等。
+     *
+     * 该本地代理类的构造函数必须允许传入远程代理对象,构造函数如:public XxxServiceStub(XxxService xxxService)
+     *
+     * 设为 true,表示使用缺省代理类名,即:接口名 + Stub 后缀
+     *
+     * 参见文档 <a href="本地存根">http://dubbo.io/books/dubbo-user-book/demos/local-stub.html</>
+     */
+    protected String stub; // TODO 芋艿
 
     // service monitor
     protected MonitorConfig monitor;
 
     // proxy type
-    protected String proxy;
+    protected String proxy; // TODO 芋艿
 
     // cluster type
     protected String cluster;
@@ -79,7 +96,7 @@
     protected Integer connections;
 
     // layer
-    protected String layer;
+    protected String layer; // TODO 芋艿
 
     // application info
     protected ApplicationConfig application;
@@ -91,19 +108,24 @@
     protected List<RegistryConfig> registries;
 
     // connection events
-    protected String onconnect;
+    protected String onconnect; // TODO 芋艿
 
     // disconnection events
-    protected String ondisconnect;
+    protected String ondisconnect; // TODO 芋艿
 
     // callback limits
     private Integer callbacks;
 
     // the scope for referring/exporting a service, if it's local, it means searching in current JVM only.
-    private String scope;
+    private String scope; // TODO 芋艿
 
+    /**
+     * 校验 RegistryConfig 配置数组。
+     * 实际上,该方法会初始化 RegistryConfig 的配置属性。
+     */
     protected void checkRegistry() {
-        // for backward compatibility
+        // 当 RegistryConfig 对象数组为空时,若有 `dubbo.registry.address` 配置,进行创建。
+        // for backward compatibility 向后兼容
         if (registries == null || registries.isEmpty()) {
             String address = ConfigUtils.getProperty("dubbo.registry.address");
             if (address != null && address.length() > 0) {
@@ -125,14 +147,20 @@ protected void checkRegistry() {
                     + Version.getVersion()
                     + ", Please add <dubbo:registry address=\"...\" /> to your spring config. If you want unregister, please set <dubbo:service registry=\"N/A\" />");
         }
+        // 读取环境变量和 properties 配置到 RegistryConfig 对象数组。
         for (RegistryConfig registryConfig : registries) {
             appendProperties(registryConfig);
         }
     }
 
+    /**
+     * 校验 ApplicationConfig 配置。
+     * 实际上,该方法会初始化 ApplicationConfig 的配置属性。
+     */
     @SuppressWarnings("deprecation")
     protected void checkApplication() {
-        // for backward compatibility
+        // 当 ApplicationConfig 对象为空时,若有 `dubbo.application.name` 配置,进行创建。
+        // for backward compatibility 向后兼容
         if (application == null) {
             String applicationName = ConfigUtils.getProperty("dubbo.application.name");
             if (applicationName != null && applicationName.length() > 0) {
@@ -143,8 +171,10 @@ protected void checkApplication() {
             throw new IllegalStateException(
                     "No such application config! Please add <dubbo:application name=\"...\" /> to your spring config.");
         }
+        // 读取环境变量和 properties 配置到 ApplicationConfig 对象。
         appendProperties(application);
 
+        // 初始化优雅停机的超时时长,参见 http://dubbo.io/books/dubbo-user-book/demos/graceful-shutdown.html 文档。
         String wait = ConfigUtils.getProperty(Constants.SHUTDOWN_WAIT_KEY);
         if (wait != null && wait.trim().length() > 0) {
             System.setProperty(Constants.SHUTDOWN_WAIT_KEY, wait.trim());
@@ -156,43 +186,60 @@ protected void checkApplication() {
         }
     }
 
+    /**
+     * 加载注册中心 URL 数组
+     *
+     * @param provider 是否是服务提供者
+     * @return URL 数组
+     */
     protected List<URL> loadRegistries(boolean provider) {
+        // 校验 RegistryConfig 配置数组。
         checkRegistry();
+        // 创建 注册中心 URL 数组
         List<URL> registryList = new ArrayList<URL>();
         if (registries != null && !registries.isEmpty()) {
             for (RegistryConfig config : registries) {
+                // 获得注册中心的地址
                 String address = config.getAddress();
                 if (address == null || address.length() == 0) {
                     address = Constants.ANYHOST_VALUE;
                 }
-                String sysaddress = System.getProperty("dubbo.registry.address");
+                String sysaddress = System.getProperty("dubbo.registry.address"); // 从启动参数读取
                 if (sysaddress != null && sysaddress.length() > 0) {
                     address = sysaddress;
                 }
-                if (address != null && address.length() > 0
+                // 有效的地址
+                if (address.length() > 0
                         && !RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) {
                     Map<String, String> map = new HashMap<String, String>();
+                    // 将各种配置对象,添加到 `map` 集合中。
                     appendParameters(map, application);
                     appendParameters(map, config);
+                    // 添加 `path` `dubbo` `timestamp` `pid` 到 `map` 集合中。
                     map.put("path", RegistryService.class.getName());
                     map.put("dubbo", Version.getVersion());
                     map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
                     if (ConfigUtils.getPid() > 0) {
                         map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
                     }
+                    // 若不存在 `protocol` 参数,默认 "dubbo" 添加到 `map` 集合中。
                     if (!map.containsKey("protocol")) {
-                        if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension("remote")) {
+                        if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension("remote")) { // "remote"
                             map.put("protocol", "remote");
                         } else {
                             map.put("protocol", "dubbo");
                         }
                     }
+                    // 解析地址,创建 Dubbo URL 数组。(数组大小可以为一)
                     List<URL> urls = UrlUtils.parseURLs(address, map);
+                    // 循环 `url` ,设置 "registry" 和 "protocol" 属性。
                     for (URL url : urls) {
+                        // 设置 `registry=${protocol}` 和 `protocol=registry` 到 URL
                         url = url.addParameter(Constants.REGISTRY_KEY, url.getProtocol());
                         url = url.setProtocol(Constants.REGISTRY_PROTOCOL);
-                        if ((provider && url.getParameter(Constants.REGISTER_KEY, true))
-                                || (!provider && url.getParameter(Constants.SUBSCRIBE_KEY, true))) {
+                        // 添加到结果
+                        if ((provider && url.getParameter(Constants.REGISTER_KEY, true)) // 服务提供者 && 注册
+                                || (!provider && url.getParameter(Constants.SUBSCRIBE_KEY, true))) { // 服务消费者 && 订阅
                             registryList.add(url);
                         }
                     }
@@ -202,7 +249,14 @@ protected void checkApplication() {
         return registryList;
     }
 
+    /**
+     * 加载监控中心 URL
+     *
+     * @param registryURL 注册中心 URL
+     * @return 监控中心 URL
+     */
     protected URL loadMonitor(URL registryURL) {
+        // 从 属性配置 中加载配置到 MonitorConfig 对象。
         if (monitor == null) {
             String monitorAddress = ConfigUtils.getProperty("dubbo.monitor.address");
             String monitorProtocol = ConfigUtils.getProperty("dubbo.monitor.protocol");
@@ -219,6 +273,7 @@ protected URL loadMonitor(URL registryURL) {
             }
         }
         appendProperties(monitor);
+        // 添加 `interface` `dubbo` `timestamp` `pid` 到 `map` 集合中
         Map<String, String> map = new HashMap<String, String>();
         map.put(Constants.INTERFACE_KEY, MonitorService.class.getName());
         map.put("dubbo", Version.getVersion());
@@ -226,13 +281,17 @@ protected URL loadMonitor(URL registryURL) {
         if (ConfigUtils.getPid() > 0) {
             map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
         }
+        // 将 MonitorConfig ,添加到 `map` 集合中。
         appendParameters(map, monitor);
+        // 获得地址
         String address = monitor.getAddress();
         String sysaddress = System.getProperty("dubbo.monitor.address");
         if (sysaddress != null && sysaddress.length() > 0) {
             address = sysaddress;
         }
+        // 直连监控中心服务器地址
         if (ConfigUtils.isNotEmpty(address)) {
+            // 若不存在 `protocol` 参数,默认 "dubbo" 添加到 `map` 集合中。
             if (!map.containsKey(Constants.PROTOCOL_KEY)) {
                 if (ExtensionLoader.getExtensionLoader(MonitorFactory.class).hasExtension("logstat")) {
                     map.put(Constants.PROTOCOL_KEY, "logstat");
@@ -240,13 +299,23 @@ protected URL loadMonitor(URL registryURL) {
                     map.put(Constants.PROTOCOL_KEY, "dubbo");
                 }
             }
+            // 解析地址,创建 Dubbo URL 对象。
             return UrlUtils.parseURL(address, map);
+        // 从注册中心发现监控中心地址
         } else if (Constants.REGISTRY_PROTOCOL.equals(monitor.getProtocol()) && registryURL != null) {
             return registryURL.setProtocol("dubbo").addParameter(Constants.PROTOCOL_KEY, "registry").addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map));
         }
         return null;
     }
 
+    /**
+     * 校验接口和方法
+     *  1. 接口类非空,并是接口
+     *  2. 方法在接口中已定义
+     *
+     * @param interfaceClass 接口类
+     * @param methods 方法数组
+     */
     protected void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConfig> methods) {
         // interface cannot be null
         if (interfaceClass == null) {
@@ -278,6 +347,12 @@ protected void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConf
         }
     }
 
+    /**
+     * 校验 Stub 和 Mock 相关的配置
+     *
+     * TODO 芋艿,后续继续研究
+     * @param interfaceClass 接口类
+     */
     protected void checkStubAndMock(Class<?> interfaceClass) {
         if (ConfigUtils.isNotEmpty(local)) {
             Class<?> localClass = ConfigUtils.isDefault(local) ? ReflectUtils.forName(interfaceClass.getName() + "Local") : ReflectUtils.forName(local);
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractMethodConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractMethodConfig.java
index 266c5db867..ea7ef8e787 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractMethodConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractMethodConfig.java
@@ -24,6 +24,10 @@
 
 /**
  * AbstractMethodConfig
+ * TODO 需要改下
+ * 方法级配置的抽象类。
+ * 属性参见:http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-method.html 。
+ *  ps:更多属性,在实现类里。
  *
  * @export
  */
@@ -38,28 +42,38 @@
     protected Integer retries;
 
     // max concurrent invocations
-    protected Integer actives;
+    protected Integer actives; // TODO 芋艿
 
     // load balance
     protected String loadbalance;
 
     // whether to async
-    protected Boolean async;
+    protected Boolean async; // TODO 芋艿
 
     // whether to ack async-sent
-    protected Boolean sent;
-
-    // the name of mock class which gets called when a service fails to execute
-    protected String mock;
+    protected Boolean sent; // TODO 芋艿
+
+    /**
+     * the name of mock class which gets called when a service fails to execute
+     * 服务接口调用失败 Mock 实现类名。
+     *
+     * 该 Mock 类必须有一个无参构造函数。
+     * 与 Stub 的区别在于,Stub 总是被执行,而Mock只在出现非业务异常(比如超时,网络异常等)时执行,Stub 在远程调用之前执行,Mock 在远程调用后执行。
+     *
+     * 设为 true,表示使用缺省Mock类名,即:接口名 + Mock 后缀
+     *
+     * 参见文档 <a href="本地伪装">http://dubbo.io/books/dubbo-user-book/demos/local-mock.html</>
+     */
+    protected String mock; // TODO 芋艿
 
     // merger
-    protected String merger;
+    protected String merger; // TODO 芋艿
 
     // cache
-    protected String cache;
+    protected String cache; // TODO 芋艿
 
     // validation
-    protected String validation;
+    protected String validation; // TODO 芋艿
 
     // customized parameters
     protected Map<String, String> parameters;
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractReferenceConfig.java
index c3f02642a1..dbc6b2fb1a 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractReferenceConfig.java
@@ -24,6 +24,8 @@
 /**
  * AbstractConsumerConfig
  *
+ * 服务消费者缺省值配置
+ *
  * @export
  * @see com.alibaba.dubbo.config.ReferenceConfig
  */
@@ -40,20 +42,25 @@
     protected Boolean init;
 
     // whether to use generic interface
-    protected String generic;
+    protected String generic; // TODO 芋艿
 
+    /**
+     * 是否 JVM 本地调用。
+     *
+     * 参见 {@link #isInjvm()} 方法,目前该属性不建议使用(废弃),使用 {@link #scope} 属性。
+     */
     // whether to find reference's instance from the current JVM
     protected Boolean injvm;
 
     // lazy create connection
     protected Boolean lazy;
 
-    protected String reconnect;
+    protected String reconnect; // TODO 芋艿
 
     protected Boolean sticky;
 
     // whether to support event in stub. //TODO solve merge problem
-    protected Boolean stubevent;//= Constants.DEFAULT_STUB_EVENT;
+    protected Boolean stubevent;//= Constants.DEFAULT_STUB_EVENT; // TODO 芋艿
 
     // version
     protected String version;
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractServiceConfig.java
index 00aed9434a..ea2dbd9c16 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractServiceConfig.java
@@ -26,6 +26,8 @@
 /**
  * AbstractServiceConfig
  *
+ * 抽象服务配置类
+ *
  * @export
  */
 public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
@@ -48,30 +50,33 @@
     protected Boolean export;
 
     // weight
-    protected Integer weight;
+    protected Integer weight; // TODO 芋艿
 
     // document center
     protected String document;
 
     // whether to register as a dynamic service or not on register center
-    protected Boolean dynamic;
+    protected Boolean dynamic; // TODO 芋艿
 
     // whether to use token
-    protected String token;
+    protected String token; // TODO 芋艿
 
     // access log
-    protected String accesslog;
+    protected String accesslog; // TODO 芋艿
+    /**
+     * 注册中心配置数组
+     */
     protected List<ProtocolConfig> protocols;
     // max allowed execute times
-    private Integer executes;
+    private Integer executes; // TODO 芋艿
     // whether to register
     private Boolean register;
 
     // warm up period
-    private Integer warmup;
+    private Integer warmup; // TODO 芋艿
 
     // serialization
-    private String serialization;
+    private String serialization; // TODO 芋艿
 
     public String getVersion() {
         return version;
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ApplicationConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ApplicationConfig.java
index 9238a11508..4ec1595225 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ApplicationConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ApplicationConfig.java
@@ -29,6 +29,9 @@
 /**
  * ApplicationConfig
  *
+ * 应用配置
+ * 属性参见 http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-application.html
+ *
  * @export
  */
 public class ApplicationConfig extends AbstractConfig {
@@ -54,10 +57,10 @@
     private String environment;
 
     // Java compiler
-    private String compiler;
+    private String compiler; // TODO 芋艿
 
     // logger
-    private String logger;
+    private String logger; // TODO 芋艿
 
     // registry centers
     private List<RegistryConfig> registries;
@@ -66,12 +69,16 @@
     private MonitorConfig monitor;
 
     // is default or not
-    private Boolean isDefault;
+    private Boolean isDefault; // TODO 芋艿
 
-    // directory for saving thread dump
-    private String dumpDirectory;
+    /**
+     * directory for saving thread dump
+     *
+     * @see <a href="http://dubbo.io/books/dubbo-user-book/demos/dump.html">线程栈自动 dump</a>
+     */
+    private String dumpDirectory; // TODO 芋艿
 
-    private Boolean qosEnable;
+    private Boolean qosEnable; // TODO 芋艿
 
     private Integer qosPort;
 
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ArgumentConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ArgumentConfig.java
index 61fff8defc..6df89c26b0 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ArgumentConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ArgumentConfig.java
@@ -21,6 +21,12 @@
 import java.io.Serializable;
 
 /**
+ * ArgumentConfig
+ *
+ * 方法参数配置。
+ * 属性参见:http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-argument.html 。
+ * 用途参见:《参数回调》http://dubbo.io/books/dubbo-user-book/demos/callback-parameter.html
+ *
  * @export
  */
 public class ArgumentConfig implements Serializable {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ConsumerConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ConsumerConfig.java
index fcf96deaa5..0ec1ae13fc 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ConsumerConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ConsumerConfig.java
@@ -19,6 +19,9 @@
 /**
  * ConsumerConfig
  *
+ * 服务消费者缺省值配置。
+ * 参数详见:http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-consumer.html
+ *
  * @export
  */
 public class ConsumerConfig extends AbstractReferenceConfig {
@@ -29,7 +32,7 @@
     private Boolean isDefault;
 
     // networking framework client uses: netty, mina, etc.
-    private String client;
+    private String client; // TODO 芋艿
 
     @Override
     public void setTimeout(Integer timeout) {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/MethodConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/MethodConfig.java
index 28230fd9e4..6b351047a2 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/MethodConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/MethodConfig.java
@@ -24,6 +24,9 @@
 /**
  * MethodConfig
  *
+ * 方法级配置。
+ * 属性参见:http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-method.html 。
+ *
  * @export
  */
 public class MethodConfig extends AbstractMethodConfig {
@@ -34,43 +37,43 @@
     private String name;
 
     // stat
-    private Integer stat;
+    private Integer stat; // TODO 芋艿
 
     // whether to retry
     private Boolean retry;
 
     // if it's reliable
-    private Boolean reliable;
+    private Boolean reliable; // TODO 芋艿
 
     // thread limits for method invocations
-    private Integer executes;
+    private Integer executes; // TODO 芋艿
 
     // if it's deprecated
     private Boolean deprecated;
 
     // whether to enable sticky
-    private Boolean sticky;
+    private Boolean sticky; // TODO 芋艿
 
     // whether need to return
-    private Boolean isReturn;
+    private Boolean isReturn; // TODO 芋艿
 
     // callback instance when async-call is invoked
-    private Object oninvoke;
+    private Object oninvoke; // TODO 芋艿
 
     // callback method when async-call is invoked
-    private String oninvokeMethod;
+    private String oninvokeMethod; // TODO 芋艿
 
     // callback instance when async-call is returned
-    private Object onreturn;
+    private Object onreturn; // TODO 芋艿
 
     // callback method when async-call is returned
-    private String onreturnMethod;
+    private String onreturnMethod; // TODO 芋艿
 
     // callback instance when async-call has exception thrown
-    private Object onthrow;
+    private Object onthrow; // TODO 芋艿
 
     // callback method when async-call has exception thrown
-    private String onthrowMethod;
+    private String onthrowMethod; // TODO 芋艿
 
     private List<ArgumentConfig> arguments;
 
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ModuleConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ModuleConfig.java
index a4e0ee9801..a197a4b09f 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ModuleConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ModuleConfig.java
@@ -24,6 +24,9 @@
 /**
  * ModuleConfig
  *
+ * 模块信息配置。
+ * 参数详见:http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-module.html
+ *
  * @export
  */
 public class ModuleConfig extends AbstractConfig {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/MonitorConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/MonitorConfig.java
index 9d51517ca5..0691d7729c 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/MonitorConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/MonitorConfig.java
@@ -23,6 +23,9 @@
 /**
  * MonitorConfig
  *
+ * 监控中心配置。
+ * 属性参见 http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-monitor.html
+ *
  * @export
  */
 public class MonitorConfig extends AbstractConfig {
@@ -33,11 +36,11 @@
 
     private String address;
 
-    private String username;
+    private String username; // TODO 芋艿
 
-    private String password;
+    private String password; // TODO 芋艿
 
-    private String group;
+    private String group; // TODO 芋艿
 
     private String version;
 
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java
index 13000a778a..1619a4eb0c 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java
@@ -36,6 +36,9 @@
 /**
  * ProtocolConfig
  *
+ * 服务提供者协议配置
+ * 属性参数 http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-protocol.html
+ *
  * @export
  */
 public class ProtocolConfig extends AbstractConfig {
@@ -54,26 +57,33 @@
     // context path
     private String contextpath;
 
+    /**
+     * 线程池名 {@link ThreadPool}
+     */
     // thread pool
     private String threadpool;
-
+    /**
+     * 线程数 {@link com.alibaba.dubbo.common.threadpool.support.fixed.FixedThreadPool}
+     */
     // thread pool size (fixed size)
     private Integer threads;
 
     // IO thread pool size (fixed size)
     private Integer iothreads;
-
+    /**
+     * 队列数
+     */
     // thread pool's queue length
     private Integer queues;
 
     // max acceptable connections
-    private Integer accepts;
+    private Integer accepts; // TODO 芋艿,
 
     // protocol codec
-    private String codec;
+    private String codec; // TODO 芋艿,
 
     // serialization
-    private String serialization;
+    private String serialization; // TODO 芋艿,
 
     // charset
     private String charset;
@@ -85,37 +95,37 @@
     private Integer buffer;
 
     // heartbeat interval
-    private Integer heartbeat;
+    private Integer heartbeat; // TODO 芋艿,
 
     // access log
-    private String accesslog;
+    private String accesslog; // TODO 芋艿,
 
     // transfort
-    private String transporter;
+    private String transporter; // TODO 芋艿,
 
     // how information is exchanged
-    private String exchanger;
+    private String exchanger; // TODO 芋艿,
 
     // thread dispatch mode
-    private String dispatcher;
+    private String dispatcher; // TODO 芋艿,
 
     // networker
-    private String networker;
+    private String networker; // TODO ,芋艿
 
     // sever impl
-    private String server;
+    private String server; // TODO ,芋艿
 
     // client impl
-    private String client;
+    private String client; // TODO ,芋艿
 
     // supported telnet commands, separated with comma.
-    private String telnet;
+    private String telnet; // TODO ,芋艿
 
     // command line prompt
-    private String prompt;
+    private String prompt; // TODO ,芋艿
 
     // status check
-    private String status;
+    private String status; // TODO ,芋艿
 
     // whether to register
     private Boolean register;
@@ -123,12 +133,12 @@
     // parameters
     // 是否长连接
     // TODO add this to provider config
-    private Boolean keepAlive;
+    private Boolean keepAlive; // TODO ,芋艿
 
     // TODO add this to provider config
-    private String optimizer;
+    private String optimizer; // TODO ,芋艿
 
-    private String extension;
+    private String extension; // TODO ,芋艿
 
     // parameters
     private Map<String, String> parameters;
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProviderConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProviderConfig.java
index 991ec53a8e..3ed6205823 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProviderConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProviderConfig.java
@@ -30,6 +30,11 @@
 /**
  * ProviderConfig
  *
+ * 服务提供者缺省值配置。
+ * 参数详见:http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-provider.html
+ *
+ * 同时该标签为 <dubbo:service> 和 <dubbo:protocol> 标签的缺省值设置。
+ *
  * @export
  * @see com.alibaba.dubbo.config.ProtocolConfig
  * @see com.alibaba.dubbo.config.ServiceConfig
@@ -53,19 +58,19 @@
     private String threadpool;
 
     // thread pool size (fixed size)
-    private Integer threads;
+    private Integer threads; // TODO 芋艿
 
     // IO thread pool size (fixed size)
-    private Integer iothreads;
+    private Integer iothreads; // TODO 芋艿
 
     // thread pool queue length
-    private Integer queues;
+    private Integer queues; // TODO 芋艿
 
     // max acceptable connections
-    private Integer accepts;
+    private Integer accepts; // TODO 芋艿
 
     // protocol codec
-    private String codec;
+    private String codec; // TODO 芋艿
 
     // charset
     private String charset;
@@ -77,34 +82,34 @@
     private Integer buffer;
 
     // transporter
-    private String transporter;
+    private String transporter; // TODO 芋艿
 
     // how information gets exchanged
-    private String exchanger;
+    private String exchanger; // TODO 芋艿
 
     // thread dispatching mode
-    private String dispatcher;
+    private String dispatcher; // TODO 芋艿
 
     // networker
-    private String networker;
+    private String networker; // TODO 芋艿
 
     // server impl
-    private String server;
+    private String server; // TODO 芋艿
 
     // client impl
-    private String client;
+    private String client; // TODO 芋艿
 
     // supported telnet commands, separated with comma.
     private String telnet;
 
     // command line prompt
-    private String prompt;
+    private String prompt; // TODO 芋艿
 
     // status check
     private String status;
 
     // wait time when stop
-    private Integer wait;
+    private Integer wait; // TODO 芋艿
 
     // if it's default
     private Boolean isDefault;
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java
index 1cb58ae28d..08d055ffd5 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java
@@ -58,35 +58,73 @@
 /**
  * ReferenceConfig
  *
+ * 服务消费者引用服务配置。
+ * 参数详细:https://dubbo.gitbooks.io/dubbo-user-book/references/xml/dubbo-reference.html
+ *
  * @export
  */
 public class ReferenceConfig<T> extends AbstractReferenceConfig {
 
     private static final long serialVersionUID = -5864351140409987595L;
 
+    /**
+     * 自适应 Protocol 实现对象
+     */
     private static final Protocol refprotocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
 
     private static final Cluster cluster = ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension();
 
+    /**
+     * 自适应 ProxyFactory 实现对象
+     */
     private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+
+    /**
+     * 服务引用 URL 数组
+     */
     private final List<URL> urls = new ArrayList<URL>();
     // interface name
     private String interfaceName;
+    /**
+     * {@link #interfaceName} 对应的接口类
+     *
+     * 非配置
+     */
     private Class<?> interfaceClass;
     // client type
     private String client;
+    /**
+     * 直连服务地址
+     *
+     * 1. 可以是注册中心,也可以是服务提供者
+     * 2. 可配置多个,使用 ; 分隔
+     */
     // url for peer-to-peer invocation
     private String url;
     // method configs
-    private List<MethodConfig> methods;
+    private List<MethodConfig> methods; // TODO 芋艿
     // default config
     private ConsumerConfig consumer;
     private String protocol;
     // interface proxy reference
+    /**
+     * Service 对象
+     */
     private transient volatile T ref;
-    private transient volatile Invoker<?> invoker;
+    private transient volatile Invoker<?> invoker; // TODO 芋艿
+    /**
+     * 是否已经初始化应用服务,参见 {@link #init()} 方法。
+     *
+     * 非配置。
+     */
     private transient volatile boolean initialized;
+    /**
+     * 是否已经销毁引用服务,参见 {@link #destroy()} 方法。
+     *
+     * 非配置。
+     */
     private transient volatile boolean destroyed;
+
     @SuppressWarnings("unused")
     private final Object finalizerGuardian = new Object() {
         @Override
@@ -114,23 +152,34 @@ public ReferenceConfig(Reference reference) {
         appendAnnotation(Reference.class, reference);
     }
 
+    /**
+     * 检查属性集合中的事件通知方法是否正确。
+     * 因为,此时方法配置的是字符串,需要通过反射获得 Method ,并添加到 attributes 。其中,键为 {@link StaticContext#getKey(Map, String, String)} 方法获取。
+     *
+     * @param method 方法配置对象
+     * @param map 参数集合
+     * @param attributes 属性集合
+     */
     private static void checkAndConvertImplicitConfig(MethodConfig method, Map<String, String> map, Map<Object, Object> attributes) {
         //check config conflict
         if (Boolean.FALSE.equals(method.isReturn()) && (method.getOnreturn() != null || method.getOnthrow() != null)) {
             throw new IllegalStateException("method config error : return attribute must be set true when onreturn or onthrow has been setted.");
         }
+        // onreturn:将方法名字符串转换成方法
         //convert onreturn methodName to Method
         String onReturnMethodKey = StaticContext.getKey(map, method.getName(), Constants.ON_RETURN_METHOD_KEY);
         Object onReturnMethod = attributes.get(onReturnMethodKey);
         if (onReturnMethod != null && onReturnMethod instanceof String) {
             attributes.put(onReturnMethodKey, getMethodByName(method.getOnreturn().getClass(), onReturnMethod.toString()));
         }
+        // onthrow:将方法名字符串转换成方法
         //convert onthrow methodName to Method
         String onThrowMethodKey = StaticContext.getKey(map, method.getName(), Constants.ON_THROW_METHOD_KEY);
         Object onThrowMethod = attributes.get(onThrowMethodKey);
         if (onThrowMethod != null && onThrowMethod instanceof String) {
             attributes.put(onThrowMethodKey, getMethodByName(method.getOnthrow().getClass(), onThrowMethod.toString()));
         }
+        // oninvoke:将方法名字符串转换成方法
         //convert oninvoke methodName to Method
         String onInvokeMethodKey = StaticContext.getKey(map, method.getName(), Constants.ON_INVOKE_METHOD_KEY);
         Object onInvokeMethod = attributes.get(onInvokeMethodKey);
@@ -156,9 +205,11 @@ public URL toUrl() {
     }
 
     public synchronized T get() {
+        // 已销毁,不可获得
         if (destroyed) {
             throw new IllegalStateException("Already destroyed!");
         }
+        // 初始化
         if (ref == null) {
             init();
         }
@@ -183,33 +234,44 @@ public synchronized void destroy() {
     }
 
     private void init() {
+        // 已经初始化,直接返回
         if (initialized) {
             return;
         }
         initialized = true;
+        // 校验接口名非空
         if (interfaceName == null || interfaceName.length() == 0) {
             throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!");
         }
+        // 拼接属性配置(环境变量 + properties 属性)到 ConsumerConfig 对象
         // get consumer's global configuration
         checkDefault();
+        // 拼接属性配置(环境变量 + properties 属性)到 ReferenceConfig 对象
         appendProperties(this);
+        // 若未设置 `generic` 属性,使用 `ConsumerConfig.generic` 属性。
         if (getGeneric() == null && getConsumer() != null) {
             setGeneric(getConsumer().getGeneric());
         }
-        if (ProtocolUtils.isGeneric(getGeneric())) {
+        // 泛化接口的实现
+        if (ProtocolUtils.isGeneric(getGeneric())) { // 【TODO 8002】芋艿,不只 true / false ,还有 bean 、 nativejava
             interfaceClass = GenericService.class;
+        // 普通接口的实现
         } else {
             try {
-                interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
-                        .getContextClassLoader());
+                interfaceClass = Class.forName(interfaceName, true, Thread.currentThread().getContextClassLoader());
             } catch (ClassNotFoundException e) {
                 throw new IllegalStateException(e.getMessage(), e);
             }
+            // 校验接口和方法
             checkInterfaceAndMethods(interfaceClass, methods);
         }
+        // 直连提供者,参见文档《直连提供者》https://dubbo.gitbooks.io/dubbo-user-book/demos/explicit-target.html
+        // 【直连提供者】第一优先级,通过 -D 参数指定 ,例如 java -Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890
         String resolve = System.getProperty(interfaceName);
         String resolveFile = null;
+        // 【直连提供者】第二优先级,通过文件映射,例如 com.alibaba.xxx.XxxService=dubbo://localhost:20890
         if (resolve == null || resolve.length() == 0) {
+            // 默认先加载,`${user.home}/dubbo-resolve.properties` 文件 ,无需配置
             resolveFile = System.getProperty("dubbo.resolve.file");
             if (resolveFile == null || resolveFile.length() == 0) {
                 File userResolveFile = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties");
@@ -217,6 +279,7 @@ private void init() {
                     resolveFile = userResolveFile.getAbsolutePath();
                 }
             }
+            // 存在 resolveFile ,则进行文件读取加载。
             if (resolveFile != null && resolveFile.length() > 0) {
                 Properties properties = new Properties();
                 FileInputStream fis = null;
@@ -235,6 +298,7 @@ private void init() {
                 resolve = properties.getProperty(interfaceName);
             }
         }
+        // 设置直连提供者的 url
         if (resolve != null && resolve.length() > 0) {
             url = resolve;
             if (logger.isWarnEnabled()) {
@@ -245,6 +309,7 @@ private void init() {
                 }
             }
         }
+        // 从 ConsumerConfig 对象中,读取 application、module、registries、monitor 配置对象。
         if (consumer != null) {
             if (application == null) {
                 application = consumer.getApplication();
@@ -259,6 +324,7 @@ private void init() {
                 monitor = consumer.getMonitor();
             }
         }
+        // 从 ModuleConfig 对象中,读取 registries、monitor 配置对象。
         if (module != null) {
             if (registries == null) {
                 registries = module.getRegistries();
@@ -267,6 +333,7 @@ private void init() {
                 monitor = module.getMonitor();
             }
         }
+        // 从 ApplicationConfig 对象中,读取 registries、monitor 配置对象。
         if (application != null) {
             if (registries == null) {
                 registries = application.getRegistries();
@@ -275,8 +342,11 @@ private void init() {
                 monitor = application.getMonitor();
             }
         }
+        // 校验 ApplicationConfig 配置。
         checkApplication();
+        // 校验 Stub 和 Mock 相关的配置
         checkStubAndMock(interfaceClass);
+        // 将 `side`,`dubbo`,`timestamp`,`pid` 参数,添加到 `map` 集合中。
         Map<String, String> map = new HashMap<String, String>();
         Map<Object, Object> attributes = new HashMap<Object, Object>();
         map.put(Constants.SIDE_KEY, Constants.CONSUMER_SIDE);
@@ -285,13 +355,14 @@ private void init() {
         if (ConfigUtils.getPid() > 0) {
             map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
         }
+        // methods、revision、interface
         if (!isGeneric()) {
             String revision = Version.getVersion(interfaceClass, version);
             if (revision != null && revision.length() > 0) {
                 map.put("revision", revision);
             }
 
-            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
+            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames(); // 【TODO 8003】Wrapper
             if (methods.length == 0) {
                 logger.warn("NO method found in service interface " + interfaceClass.getName());
                 map.put("methods", Constants.ANY_VALUE);
@@ -300,14 +371,19 @@ private void init() {
             }
         }
         map.put(Constants.INTERFACE_KEY, interfaceName);
+        // 将各种配置对象,添加到 `map` 集合中。
         appendParameters(map, application);
         appendParameters(map, module);
         appendParameters(map, consumer, Constants.DEFAULT_KEY);
         appendParameters(map, this);
+        // 获得服务键,作为前缀
         String prefix = StringUtils.getServiceKey(map);
+        // 将 MethodConfig 对象数组,添加到 `map` 集合中。
         if (methods != null && !methods.isEmpty()) {
             for (MethodConfig method : methods) {
+                // 将 MethodConfig 对象,添加到 `map` 集合中。
                 appendParameters(map, method, method.getName());
+                // 当 配置了 `MethodConfig.retry = false` 时,强制禁用重试
                 String retryKey = method.getName() + ".retry";
                 if (map.containsKey(retryKey)) {
                     String retryValue = map.remove(retryKey);
@@ -315,11 +391,14 @@ private void init() {
                         map.put(method.getName() + ".retries", "0");
                     }
                 }
+                // 将带有 @Parameter(attribute = true) 配置对象的属性,添加到参数集合。参见《事件通知》http://dubbo.io/books/dubbo-user-book/demos/events-notify.html
                 appendAttributes(attributes, method, prefix + "." + method.getName());
+                // 检查属性集合中的事件通知方法是否正确。若正确,进行转换。
                 checkAndConvertImplicitConfig(method, map, attributes);
             }
         }
 
+        // 以系统环境变量( DUBBO_IP_TO_REGISTRY ) 作为服务注册地址,参见 https://github.com/dubbo/dubbo-docker-sample 项目。
         String hostToRegistry = ConfigUtils.getSystemProperty(Constants.DUBBO_IP_TO_REGISTRY);
         if (hostToRegistry == null || hostToRegistry.length() == 0) {
             hostToRegistry = NetUtils.getLocalHost();
@@ -328,61 +407,95 @@ private void init() {
         }
         map.put(Constants.REGISTER_IP_KEY, hostToRegistry);
 
+        // 添加到 StaticContext 进行缓存
         //attributes are stored by system context.
         StaticContext.getSystemContext().putAll(attributes);
+
+        // 创建 Service 代理对象
         ref = createProxy(map);
+
+        // TODO 芋艿
         ConsumerModel consumerModel = new ConsumerModel(getUniqueServiceName(), this, ref, interfaceClass.getMethods());
         ApplicationModel.initConsumerModel(getUniqueServiceName(), consumerModel);
     }
 
+    /**
+     * 创建 Service 代理对象
+     *
+     * @param map 集合
+     * @return 代理对象
+     */
     @SuppressWarnings({"unchecked", "rawtypes", "deprecation"})
     private T createProxy(Map<String, String> map) {
         URL tmpUrl = new URL("temp", "localhost", 0, map);
+        // 是否本地引用
         final boolean isJvmRefer;
+        // injvm 属性为空,不通过该属性判断
         if (isInjvm() == null) {
+            // 直连服务提供者,参见文档《直连提供者》https://dubbo.gitbooks.io/dubbo-user-book/demos/explicit-target.html
             if (url != null && url.length() > 0) { // if a url is specified, don't do local reference
                 isJvmRefer = false;
+            // 通过 `tmpUrl` 判断,是否需要本地引用
             } else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
                 // by default, reference local service if there is
                 isJvmRefer = true;
+            // 默认不是
             } else {
                 isJvmRefer = false;
             }
+        // 通过 injvm 属性。
         } else {
-            isJvmRefer = isInjvm().booleanValue();
+            isJvmRefer = isInjvm();
         }
 
+        // 本地引用
         if (isJvmRefer) {
+            // 创建本地服务引用 URL 对象。
             URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
+            // 引用服务,返回 Invoker 对象
             invoker = refprotocol.refer(interfaceClass, url);
             if (logger.isInfoEnabled()) {
                 logger.info("Using injvm service " + interfaceClass.getName());
             }
+        // 正常流程,一般为远程引用
         } else {
+            // 定义直连地址,可以是服务提供者的地址,也可以是注册中心的地址
             if (url != null && url.length() > 0) { // user specified URL, could be peer-to-peer address, or register center's address.
+                // 拆分地址成数组,使用 ";" 分隔。
                 String[] us = Constants.SEMICOLON_SPLIT_PATTERN.split(url);
+                // 循环数组,添加到 `url` 中。
                 if (us != null && us.length > 0) {
                     for (String u : us) {
+                        // 创建 URL 对象
                         URL url = URL.valueOf(u);
+                        // 设置默认路径
                         if (url.getPath() == null || url.getPath().length() == 0) {
                             url = url.setPath(interfaceName);
                         }
+                        // 注册中心的地址,带上服务引用的配置参数
                         if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                             urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
+                        // 服务提供者的地址
                         } else {
                             urls.add(ClusterUtils.mergeUrl(url, map));
                         }
                     }
                 }
+            // 注册中心
             } else { // assemble URL from register center's configuration
+                // 加载注册中心 URL 数组
                 List<URL> us = loadRegistries(false);
+                // 循环数组,添加到 `url` 中。
                 if (us != null && !us.isEmpty()) {
                     for (URL u : us) {
+                        // 加载监控中心 URL
                         URL monitorUrl = loadMonitor(u);
+                        // 服务引用配置对象 `map`,带上监控中心的 URL
                         if (monitorUrl != null) {
                             map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
                         }
-                        urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
+                        // 注册中心的地址,带上服务引用的配置参数
+                        urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map))); // 注册中心,带上服务引用的配置参数
                     }
                 }
                 if (urls == null || urls.isEmpty()) {
@@ -390,27 +503,38 @@ private T createProxy(Map<String, String> map) {
                 }
             }
 
+            // 单 `urls` 时,引用服务,返回 Invoker 对象
             if (urls.size() == 1) {
+                // 引用服务
                 invoker = refprotocol.refer(interfaceClass, urls.get(0));
             } else {
+                // 循环 `urls` ,引用服务,返回 Invoker 对象
                 List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
                 URL registryURL = null;
                 for (URL url : urls) {
+                    // 引用服务
                     invokers.add(refprotocol.refer(interfaceClass, url));
+                    // 使用最后一个注册中心的 URL
                     if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                         registryURL = url; // use last registry url
                     }
                 }
+                // 有注册中心
                 if (registryURL != null) { // registry url is available
+                    // 对有注册中心的 Cluster 只用 AvailableCluster
                     // use AvailableCluster only when register's cluster is available
                     URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
+                    // TODO 芋艿
                     invoker = cluster.join(new StaticDirectory(u, invokers));
+                // 无注册中心
                 } else { // not a registry url
+                    // TODO 芋艿
                     invoker = cluster.join(new StaticDirectory(invokers));
                 }
             }
         }
 
+        // 启动时检查
         Boolean c = check;
         if (c == null && consumer != null) {
             c = consumer.isCheck();
@@ -424,10 +548,16 @@ private T createProxy(Map<String, String> map) {
         if (logger.isInfoEnabled()) {
             logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
         }
+
+        // 创建 Service 代理对象
         // create service proxy
         return (T) proxyFactory.getProxy(invoker);
     }
 
+    /**
+     * 校验 ConsumerConfig 配置。
+     * 实际上,会拼接属性配置(环境变量 + properties 属性)到 ConsumerConfig 对象。
+     */
     private void checkDefault() {
         if (consumer == null) {
             consumer = new ConsumerConfig();
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/RegistryConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/RegistryConfig.java
index 7e2672b9c3..886bdd1334 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/RegistryConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/RegistryConfig.java
@@ -25,12 +25,16 @@
 /**
  * RegistryConfig
  *
+ * 注册中心配置。
+ * 属性参见 http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-registry.html
+ *
  * @export
  */
 public class RegistryConfig extends AbstractConfig {
 
     public static final String NO_AVAILABLE = "N/A";
     private static final long serialVersionUID = 5508512956753757169L;
+
     // register center address
     private String address;
 
@@ -44,20 +48,20 @@
     private Integer port;
 
     // protocol for register center
-    private String protocol;
+    private String protocol; // TODO 芋艿
 
     // client impl
-    private String transporter;
+    private String transporter; // TODO 芋艿
 
-    private String server;
+    private String server; // TODO 芋艿
 
-    private String client;
+    private String client; // TODO 芋艿
 
-    private String cluster;
+    private String cluster; // TODO 芋艿
 
-    private String group;
+    private String group; // TODO 芋艿
 
-    private String version;
+    private String version; // TODO 芋艿
 
     // request timeout in milliseconds for register center
     private Integer timeout;
@@ -114,7 +118,7 @@ public void setProtocol(String protocol) {
         this.protocol = protocol;
     }
 
-    @Parameter(excluded = true)
+    @Parameter(excluded = true) // 排除
     public String getAddress() {
         return address;
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java
index dfb633790a..2593a63380 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java
@@ -65,36 +65,92 @@
 /**
  * ServiceConfig
  *
+ * 服务提供者暴露服务配置。
+ * 参数详细:http://dubbo.io/books/dubbo-user-book/references/xml/dubbo-service.html
+ *
  * @export
  */
 public class ServiceConfig<T> extends AbstractServiceConfig {
 
     private static final long serialVersionUID = 3033787999037024738L;
 
+    /**
+     * 自适应 Protocol 实现对象
+     */
     private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
 
+    /**
+     * 自适应 ProxyFactory 实现对象
+     */
     private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
 
+    /**
+     * 协议名对应生成的随机端口
+     *
+     * key :协议名
+     * value :端口
+     */
     private static final Map<String, Integer> RANDOM_PORT_MAP = new HashMap<String, Integer>();
 
+    /**
+     * 延迟暴露执行器
+     */
     private static final ScheduledExecutorService delayExportExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboServiceDelayExporter", true));
+
+    /**
+     * 服务配置对应的 Dubbo URL 数组
+     *
+     * 非配置。
+     */
     private final List<URL> urls = new ArrayList<URL>();
+    /**
+     * 服务配置暴露的 Exporter 。
+     * URL :Exporter 不一定是 1:1 的关系。
+     * 例如 {@link #scope} 未设置时,会暴露 Local + Remote 两个,也就是 URL :Exporter = 1:2
+     *      {@link #scope} 设置为空时,不会暴露,也就是 URL :Exporter = 1:0
+     *      {@link #scope} 设置为 Local 或 Remote 任一时,会暴露 Local 或 Remote 一个,也就是 URL :Exporter = 1:1
+     *
+     * 非配置。
+     */
     private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();
     // interface type
     private String interfaceName;
+    /**
+     * {@link #interfaceName} 对应的接口类
+     *
+     * 非配置
+     */
     private Class<?> interfaceClass;
+    /**
+     * Service 对象
+     */
     // reference to interface impl
     private T ref;
     // service name
-    private String path;
+    private String path; // TODO 芋艿
     // method configuration
     private List<MethodConfig> methods;
     private ProviderConfig provider;
-    private transient volatile boolean exported;
 
+    /**
+     * 是否已经暴露服务,参见 {@link #doExport()} 方法。
+     *
+     * 非配置。
+     */
+    private transient volatile boolean exported;
+    /**
+     * 是否已取消暴露服务,参见 {@link #unexport()} 方法。
+     *
+     * 非配置。
+     */
     private transient volatile boolean unexported;
-
-    private volatile String generic;
+    /**
+     * 是否泛化实现,参见 <a href="https://dubbo.gitbooks.io/dubbo-user-book/demos/generic-service.html">实现泛化调用</a>
+     * true / false
+     *
+     * 状态字段,非配置。
+     */
+    private volatile String generic; // TODO 芋艿
 
     public ServiceConfig() {
     }
@@ -159,6 +215,13 @@ private static final ProviderConfig convertProtocolToProvider(ProtocolConfig pro
         return provider;
     }
 
+    /**
+     * 从缓存中获得协议名对应的端口。
+     * 避免相同的协议名,随机的端口是一致的。
+     *
+     * @param protocol 协议名
+     * @return 端口
+     */
     private static Integer getRandomPort(String protocol) {
         protocol = protocol.toLowerCase();
         if (RANDOM_PORT_MAP.containsKey(protocol)) {
@@ -167,6 +230,12 @@ private static Integer getRandomPort(String protocol) {
         return Integer.MIN_VALUE;
     }
 
+    /**
+     * 添加随机端口到缓存中
+     *
+     * @param protocol 协议名
+     * @param port 端口
+     */
     private static void putRandomPort(String protocol, Integer port) {
         protocol = protocol.toLowerCase();
         if (!RANDOM_PORT_MAP.containsKey(protocol)) {
@@ -192,7 +261,11 @@ public boolean isUnexported() {
         return unexported;
     }
 
+    /**
+     * 暴露服务
+     */
     public synchronized void export() {
+        // 当 export 或者 delay 未配置,从 ProviderConfig 对象读取。
         if (provider != null) {
             if (export == null) {
                 export = provider.getExport();
@@ -201,22 +274,29 @@ public synchronized void export() {
                 delay = provider.getDelay();
             }
         }
+        // 不暴露服务( export = false ) ,则不进行暴露服务逻辑。
         if (export != null && !export) {
             return;
         }
 
+        // 延迟暴露
         if (delay != null && delay > 0) {
             delayExportExecutor.schedule(new Runnable() {
                 public void run() {
                     doExport();
                 }
             }, delay, TimeUnit.MILLISECONDS);
+        // 立即暴露
         } else {
             doExport();
         }
     }
 
+    /**
+     * 执行暴露服务
+     */
     protected synchronized void doExport() {
+        // 检查是否可以暴露,若可以,标记已经暴露。
         if (unexported) {
             throw new IllegalStateException("Already unexported!");
         }
@@ -224,10 +304,13 @@ protected synchronized void doExport() {
             return;
         }
         exported = true;
+        // 校验接口名非空
         if (interfaceName == null || interfaceName.length() == 0) {
             throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
         }
+        // 拼接属性配置(环境变量 + properties 属性)到 ProviderConfig 对象
         checkDefault();
+        // 从 ProviderConfig 对象中,读取 application、module、registries、monitor、protocols 配置对象。
         if (provider != null) {
             if (application == null) {
                 application = provider.getApplication();
@@ -245,6 +328,7 @@ protected synchronized void doExport() {
                 protocols = provider.getProtocols();
             }
         }
+        // 从 ModuleConfig 对象中,读取 registries、monitor 配置对象。
         if (module != null) {
             if (registries == null) {
                 registries = module.getRegistries();
@@ -253,6 +337,7 @@ protected synchronized void doExport() {
                 monitor = module.getMonitor();
             }
         }
+        // 从 ApplicationConfig 对象中,读取 registries、monitor 配置对象。
         if (application != null) {
             if (registries == null) {
                 registries = application.getRegistries();
@@ -261,23 +346,28 @@ protected synchronized void doExport() {
                 monitor = application.getMonitor();
             }
         }
+        // 泛化接口的实现
         if (ref instanceof GenericService) {
             interfaceClass = GenericService.class;
             if (StringUtils.isEmpty(generic)) {
                 generic = Boolean.TRUE.toString();
             }
+        // 普通接口的实现
         } else {
             try {
-                interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
-                        .getContextClassLoader());
+                interfaceClass = Class.forName(interfaceName, true, Thread.currentThread().getContextClassLoader());
             } catch (ClassNotFoundException e) {
                 throw new IllegalStateException(e.getMessage(), e);
             }
+            // 校验接口和方法
             checkInterfaceAndMethods(interfaceClass, methods);
+            // 校验指向的 service 对象
             checkRef();
             generic = Boolean.FALSE.toString();
         }
+        // 处理服务接口客户端本地代理( `local` )相关。实际目前已经废弃,使用 `stub` 属性,参见 `AbstractInterfaceConfig#setLocal` 方法。
         if (local != null) {
+            // 设为 true,表示使用缺省代理类名,即:接口名 + Local 后缀
             if ("true".equals(local)) {
                 local = interfaceName + "Local";
             }
@@ -291,7 +381,9 @@ protected synchronized void doExport() {
                 throw new IllegalStateException("The local implementation class " + localClass.getName() + " not implement interface " + interfaceName);
             }
         }
+        // 处理服务接口客户端本地代理( `stub` )相关
         if (stub != null) {
+            // 设为 true,表示使用缺省代理类名,即:接口名 + Stub 后缀
             if ("true".equals(stub)) {
                 stub = interfaceName + "Stub";
             }
@@ -305,19 +397,32 @@ protected synchronized void doExport() {
                 throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + interfaceName);
             }
         }
+        // 校验 ApplicationConfig 配置。
         checkApplication();
+        // 校验 RegistryConfig 配置。
         checkRegistry();
+        // 校验 ProtocolConfig 配置数组。
         checkProtocol();
+        // 读取环境变量和 properties 配置到 ServiceConfig 对象。
         appendProperties(this);
+        // 校验 Stub 和 Mock 相关的配置
         checkStubAndMock(interfaceClass);
+        // 服务路径,缺省为接口名
         if (path == null || path.length() == 0) {
             path = interfaceName;
         }
+        // 暴露
         doExportUrls();
+        // TODO 芋艿,等待 qos
         ProviderModel providerModel = new ProviderModel(getUniqueServiceName(), this, ref);
         ApplicationModel.initProviderModel(getUniqueServiceName(), providerModel);
     }
 
+    /**
+     * 校验指向的 service 对象
+     *  1. 非空
+     *  2. 实现 {@link #interfaceClass} 接口
+     */
     private void checkRef() {
         // reference should not be null, and is the implementation of the given interface
         if (ref == null) {
@@ -350,20 +455,33 @@ public synchronized void unexport() {
         unexported = true;
     }
 
+    /**
+     * 暴露 Dubbo URL
+     */
     @SuppressWarnings({"unchecked", "rawtypes"})
     private void doExportUrls() {
+        // 加载注册中心 URL 数组
         List<URL> registryURLs = loadRegistries(true);
+        // 循环 `protocols` ,向逐个注册中心分组暴露服务。
         for (ProtocolConfig protocolConfig : protocols) {
             doExportUrlsFor1Protocol(protocolConfig, registryURLs);
         }
     }
 
+    /**
+     * 基于单个协议,暴露服务
+     *
+     * @param protocolConfig 协议配置对象
+     * @param registryURLs 注册中心链接对象数组
+     */
     private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
+        // 协议名
         String name = protocolConfig.getName();
         if (name == null || name.length() == 0) {
             name = "dubbo";
         }
 
+        // 将 `side`,`dubbo`,`timestamp`,`pid` 参数,添加到 `map` 集合中。
         Map<String, String> map = new HashMap<String, String>();
         map.put(Constants.SIDE_KEY, Constants.PROVIDER_SIDE);
         map.put(Constants.DUBBO_VERSION_KEY, Version.getVersion());
@@ -371,14 +489,18 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
         if (ConfigUtils.getPid() > 0) {
             map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
         }
+        // 将各种配置对象,添加到 `map` 集合中。
         appendParameters(map, application);
         appendParameters(map, module);
-        appendParameters(map, provider, Constants.DEFAULT_KEY);
+        appendParameters(map, provider, Constants.DEFAULT_KEY); // ProviderConfig ,为 ServiceConfig 的默认属性,因此添加 `default` 属性前缀。
         appendParameters(map, protocolConfig);
         appendParameters(map, this);
+        // 将 MethodConfig 对象数组,添加到 `map` 集合中。
         if (methods != null && !methods.isEmpty()) {
             for (MethodConfig method : methods) {
+                // 将 MethodConfig 对象,添加到 `map` 集合中。
                 appendParameters(map, method, method.getName());
+                // 当 配置了 `MethodConfig.retry = false` 时,强制禁用重试
                 String retryKey = method.getName() + ".retry";
                 if (map.containsKey(retryKey)) {
                     String retryValue = map.remove(retryKey);
@@ -386,33 +508,36 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
                         map.put(method.getName() + ".retries", "0");
                     }
                 }
+                // 将 ArgumentConfig 对象数组,添加到 `map` 集合中。
                 List<ArgumentConfig> arguments = method.getArguments();
                 if (arguments != null && !arguments.isEmpty()) {
                     for (ArgumentConfig argument : arguments) {
                         // convert argument type
-                        if (argument.getType() != null && argument.getType().length() > 0) {
+                        if (argument.getType() != null && argument.getType().length() > 0) { // 指定了类型
                             Method[] methods = interfaceClass.getMethods();
                             // visit all methods
                             if (methods != null && methods.length > 0) {
                                 for (int i = 0; i < methods.length; i++) {
                                     String methodName = methods[i].getName();
                                     // target the method, and get its signature
-                                    if (methodName.equals(method.getName())) {
-                                        Class<?>[] argtypes = methods[i].getParameterTypes();
+                                    if (methodName.equals(method.getName())) { // 找到指定方法
+                                        Class<?>[] argTypes = methods[i].getParameterTypes();
                                         // one callback in the method
-                                        if (argument.getIndex() != -1) {
-                                            if (argtypes[argument.getIndex()].getName().equals(argument.getType())) {
-                                                appendParameters(map, argument, method.getName() + "." + argument.getIndex());
+                                        if (argument.getIndex() != -1) { // 指定单个参数的位置 + 类型
+                                            if (argTypes[argument.getIndex()].getName().equals(argument.getType())) {
+                                                // 将 ArgumentConfig 对象,添加到 `map` 集合中。
+                                                appendParameters(map, argument, method.getName() + "." + argument.getIndex()); // `${methodName}.${index}`
                                             } else {
                                                 throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                                             }
                                         } else {
                                             // multiple callbacks in the method
-                                            for (int j = 0; j < argtypes.length; j++) {
-                                                Class<?> argclazz = argtypes[j];
-                                                if (argclazz.getName().equals(argument.getType())) {
-                                                    appendParameters(map, argument, method.getName() + "." + j);
-                                                    if (argument.getIndex() != -1 && argument.getIndex() != j) {
+                                            for (int j = 0; j < argTypes.length; j++) {
+                                                Class<?> argClazz = argTypes[j];
+                                                if (argClazz.getName().equals(argument.getType())) {
+                                                    // 将 ArgumentConfig 对象,添加到 `map` 集合中。
+                                                    appendParameters(map, argument, method.getName() + "." + j); // `${methodName}.${index}`
+                                                    if (argument.getIndex() != -1 && argument.getIndex() != j) { // 多余的判断,因为 `argument.getIndex() == -1` 。
                                                         throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                                                     }
                                                 }
@@ -421,8 +546,9 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
                                     }
                                 }
                             }
-                        } else if (argument.getIndex() != -1) {
-                            appendParameters(map, argument, method.getName() + "." + argument.getIndex());
+                        } else if (argument.getIndex() != -1) { // 指定单个参数的位置
+                            // 将 ArgumentConfig 对象,添加到 `map` 集合中。
+                            appendParameters(map, argument, method.getName() + "." + argument.getIndex()); // `${methodName}.${index}`
                         } else {
                             throw new IllegalArgumentException("argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");
                         }
@@ -432,16 +558,17 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
             } // end of methods for
         }
 
+        // generic、methods、revision
         if (ProtocolUtils.isGeneric(generic)) {
             map.put("generic", generic);
             map.put("methods", Constants.ANY_VALUE);
         } else {
             String revision = Version.getVersion(interfaceClass, version);
             if (revision != null && revision.length() > 0) {
-                map.put("revision", revision);
+                map.put("revision", revision); // 修订本
             }
 
-            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
+            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames(); // 【TODO 8003】Wrapper
             if (methods.length == 0) {
                 logger.warn("NO method found in service interface " + interfaceClass.getName());
                 map.put("methods", Constants.ANY_VALUE);
@@ -449,6 +576,7 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
                 map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
             }
         }
+        // token ,参见《令牌校验》https://dubbo.gitbooks.io/dubbo-user-book/demos/token-authorization.html
         if (!ConfigUtils.isEmpty(token)) {
             if (ConfigUtils.isDefault(token)) {
                 map.put("token", UUID.randomUUID().toString());
@@ -456,6 +584,7 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
                 map.put("token", token);
             }
         }
+        // 协议为 injvm 时,不注册,不通知。
         if ("injvm".equals(protocolConfig.getName())) {
             protocolConfig.setRegister(false);
             map.put("notify", "false");
@@ -466,10 +595,14 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
             contextPath = provider.getContextpath();
         }
 
+        // host、port
         String host = this.findConfigedHosts(protocolConfig, registryURLs, map);
         Integer port = this.findConfigedPorts(protocolConfig, name, map);
+
+        // 创建 Dubbo URL 对象
         URL url = new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map);
 
+        // 配置规则,参见《配置规则》https://dubbo.gitbooks.io/dubbo-user-book/demos/config-rule.html
         if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
                 .hasExtension(url.getProtocol())) {
             url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
@@ -480,10 +613,13 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
         // don't export when none is configured
         if (!Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {
 
+            // 服务本地暴露
             // export to local if the config is not remote (export to remote only when config is remote)
             if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {
                 exportLocal(url);
             }
+
+            // 服务远程暴露
             // export to remote if the config is not local (export to local only when config is local)
             if (!Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope)) {
                 if (logger.isInfoEnabled()) {
@@ -491,25 +627,37 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
                 }
                 if (registryURLs != null && !registryURLs.isEmpty()) {
                     for (URL registryURL : registryURLs) {
+                        // "dynamic" :服务是否动态注册,如果设为false,注册后将显示后disable状态,需人工启用,并且服务提供者停止时,也不会自动取消册,需人工禁用。
                         url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));
-                        URL monitorUrl = loadMonitor(registryURL);
+                        // 获得监控中心 URL
+                        URL monitorUrl = loadMonitor(registryURL); // TODO 芋艿,监控
                         if (monitorUrl != null) {
                             url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());
                         }
                         if (logger.isInfoEnabled()) {
                             logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
                         }
+                        // 使用 ProxyFactory 创建 Invoker 对象
                         Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
+
+                        // 创建 DelegateProviderMetaDataInvoker 对象
                         DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
 
+                        // 使用 Protocol 暴露 Invoker 对象
                         Exporter<?> exporter = protocol.export(wrapperInvoker);
+                        // 添加到 `exporters`
                         exporters.add(exporter);
                     }
-                } else {
+                } else { // 用于被服务消费者直连服务提供者,参见文档 http://dubbo.io/books/dubbo-user-book/demos/explicit-target.html 。主要用于开发测试环境使用。
+                    // 使用 ProxyFactory 创建 Invoker 对象
                     Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
+
+                    // 创建 DelegateProviderMetaDataInvoker 对象
                     DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
 
+                    // 使用 Protocol 暴露 Invoker 对象
                     Exporter<?> exporter = protocol.export(wrapperInvoker);
+                    // 添加到 `exporters`
                     exporters.add(exporter);
                 }
             }
@@ -517,16 +665,25 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> r
         this.urls.add(url);
     }
 
+    /**
+     * 本地暴露服务
+     *
+     * @param url 注册中心 URL
+     */
     @SuppressWarnings({"unchecked", "rawtypes"})
     private void exportLocal(URL url) {
         if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
+            // 创建本地 Dubbo URL
             URL local = URL.valueOf(url.toFullString())
-                    .setProtocol(Constants.LOCAL_PROTOCOL)
-                    .setHost(LOCALHOST)
-                    .setPort(0);
+                    .setProtocol(Constants.LOCAL_PROTOCOL) // injvm
+                    .setHost(LOCALHOST) // 本地
+                    .setPort(0); // 端口=0
+            // 添加服务的真实类名,例如 DemoServiceImpl ,仅用于 RestProtocol 中。
             ServiceClassHolder.getInstance().pushServiceClass(getServiceClass(ref));
-            Exporter<?> exporter = protocol.export(
-                    proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
+            // 使用 ProxyFactory 创建 Invoker 对象
+            // 使用 Protocol 暴露 Invoker 对象
+            Exporter<?> exporter = protocol.export(proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
+            // 添加到 `exporters`
             exporters.add(exporter);
             logger.info("Export dubbo service " + interfaceClass.getName() + " to local registry");
         }
@@ -537,29 +694,36 @@ protected Class getServiceClass(T ref) {
     }
 
     /**
+     * 查找主机 Host ,参见文档《主机绑定》https://dubbo.gitbooks.io/dubbo-user-book/demos/hostname-binding.html
+     *
+     * 推荐阅读文章《dubbo注册服务IP解析异常及IP解析源码分析》 https://segmentfault.com/a/1190000010550512
+     *
      * Register & bind IP address for service provider, can be configured separately.
      * Configuration priority: environment variables -> java system properties -> host property in config file ->
      * /etc/hosts -> default network address -> first available network address
      *
-     * @param protocolConfig
-     * @param registryURLs
-     * @param map
+     * @param protocolConfig 协议配置对象
+     * @param registryURLs 注册中心 URL 数组
+     * @param map 参数集合
      * @return
      */
     private String findConfigedHosts(ProtocolConfig protocolConfig, List<URL> registryURLs, Map<String, String> map) {
         boolean anyhost = false;
 
+        // 第一优先级,从环境变量,获得绑定的 Host 。可强制指定,参见仓库 https://github.com/dubbo/dubbo-docker-sample
         String hostToBind = getValueFromConfig(protocolConfig, Constants.DUBBO_IP_TO_BIND);
-        if (hostToBind != null && hostToBind.length() > 0 && isInvalidLocalHost(hostToBind)) {
+        if (hostToBind != null && hostToBind.length() > 0 && isInvalidLocalHost(hostToBind)) { // 若是非法的本地 Host 【这个方法,胖友需要看下的】,抛出异常
             throw new IllegalArgumentException("Specified invalid bind ip from property:" + Constants.DUBBO_IP_TO_BIND + ", value:" + hostToBind);
         }
 
         // if bind ip is not found in environment, keep looking up
         if (hostToBind == null || hostToBind.length() == 0) {
+            // 第二优先级,从 ProtocolConfig 获得 Host 。
             hostToBind = protocolConfig.getHost();
             if (provider != null && (hostToBind == null || hostToBind.length() == 0)) {
                 hostToBind = provider.getHost();
             }
+            // 第三优先级,若非合法的本地 Host ,使用 InetAddress.getLocalHost().getHostAddress() 获得 Host
             if (isInvalidLocalHost(hostToBind)) {
                 anyhost = true;
                 try {
@@ -567,6 +731,7 @@ private String findConfigedHosts(ProtocolConfig protocolConfig, List<URL> regist
                 } catch (UnknownHostException e) {
                     logger.warn(e.getMessage(), e);
                 }
+                // 第四优先级,若是非法的本地 Host ,通过使用 `registryURLs` 启动 Server ,并本地连接,获得 Host 。
                 if (isInvalidLocalHost(hostToBind)) {
                     if (registryURLs != null && !registryURLs.isEmpty()) {
                         for (URL registryURL : registryURLs) {
@@ -588,6 +753,7 @@ private String findConfigedHosts(ProtocolConfig protocolConfig, List<URL> regist
                             }
                         }
                     }
+                    // 第五优先级,若是非法的本地 Host ,获得本地网卡,第一个合法的 IP 。
                     if (isInvalidLocalHost(hostToBind)) {
                         hostToBind = getLocalHost();
                     }
@@ -597,6 +763,7 @@ private String findConfigedHosts(ProtocolConfig protocolConfig, List<URL> regist
 
         map.put(Constants.BIND_IP_KEY, hostToBind);
 
+        // 获得 `hostToRegistry` ,默认使用 `hostToBind` 。可强制指定,参见仓库 https://github.com/dubbo/dubbo-docker-sample
         // registry ip is not used for bind ip by default
         String hostToRegistry = getValueFromConfig(protocolConfig, Constants.DUBBO_IP_TO_REGISTRY);
         if (hostToRegistry != null && hostToRegistry.length() > 0 && isInvalidLocalHost(hostToRegistry)) {
@@ -612,35 +779,41 @@ private String findConfigedHosts(ProtocolConfig protocolConfig, List<URL> regist
     }
 
     /**
+     * 查找端口,参见文档《主机绑定》https://dubbo.gitbooks.io/dubbo-user-book/demos/hostname-binding.html
+     *
      * Register port and bind port for the provider, can be configured separately
      * Configuration priority: environment variable -> java system properties -> port property in protocol config file
      * -> protocol default port
      *
-     * @param protocolConfig
-     * @param name
-     * @return
+     * @param protocolConfig 协议配置对象
+     * @param name 协议名
+     * @return 端口
      */
     private Integer findConfigedPorts(ProtocolConfig protocolConfig, String name, Map<String, String> map) {
-        Integer portToBind = null;
-
+        // 第一优先级,从环境变量,获得绑定的 Port 。可强制指定,参见仓库 https://github.com/dubbo/dubbo-docker-sample
         // parse bind port from environment
         String port = getValueFromConfig(protocolConfig, Constants.DUBBO_PORT_TO_BIND);
-        portToBind = parsePort(port);
+        Integer portToBind = parsePort(port);
 
         // if there's no bind port found from environment, keep looking up.
         if (portToBind == null) {
+            // 第二优先级,从 ProtocolConfig 获得 Port 。
             portToBind = protocolConfig.getPort();
             if (provider != null && (portToBind == null || portToBind == 0)) {
                 portToBind = provider.getPort();
             }
+            // 第三优先级,获得协议对应的缺省端口,
             final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
             if (portToBind == null || portToBind == 0) {
                 portToBind = defaultPort;
             }
-            if (portToBind == null || portToBind <= 0) {
-                portToBind = getRandomPort(name);
+            // 第四优先级,随机获得端口
+            if (portToBind <= 0) {
+                portToBind = getRandomPort(name); // 先从缓存中获得端口
                 if (portToBind == null || portToBind < 0) {
+                    // 获得可用端口
                     portToBind = getAvailablePort(defaultPort);
+                    // 添加到缓存
                     putRandomPort(name, portToBind);
                 }
                 logger.warn("Use random available port(" + portToBind + ") for protocol " + name);
@@ -650,6 +823,7 @@ private Integer findConfigedPorts(ProtocolConfig protocolConfig, String name, Ma
         // save bind port, used as url's key later
         map.put(Constants.BIND_PORT_KEY, String.valueOf(portToBind));
 
+        // 获得 `portToRegistry` ,默认使用 `portToBind` 。可强制指定,参见仓库 https://github.com/dubbo/dubbo-docker-sample
         // registry port, not used as bind port by default
         String portToRegistryStr = getValueFromConfig(protocolConfig, Constants.DUBBO_PORT_TO_REGISTRY);
         Integer portToRegistry = parsePort(portToRegistryStr);
@@ -660,6 +834,12 @@ private Integer findConfigedPorts(ProtocolConfig protocolConfig, String name, Ma
         return portToRegistry;
     }
 
+    /**
+     * 解析端口字符串
+     *
+     * @param configPort 端口字符串
+     * @return 端口
+     */
     private Integer parsePort(String configPort) {
         Integer port = null;
         if (configPort != null && configPort.length() > 0) {
@@ -676,6 +856,13 @@ private Integer parsePort(String configPort) {
         return port;
     }
 
+    /**
+     * 从协议配置对象解析对应的配置项
+     *
+     * @param protocolConfig 协议配置对象
+     * @param key 配置项
+     * @return 值
+     */
     private String getValueFromConfig(ProtocolConfig protocolConfig, String key) {
         String protocolPrefix = protocolConfig.getName().toUpperCase() + "_";
         String port = ConfigUtils.getSystemProperty(protocolPrefix + key);
@@ -685,6 +872,10 @@ private String getValueFromConfig(ProtocolConfig protocolConfig, String key) {
         return port;
     }
 
+    /**
+     * 校验 ProviderConfig 配置。
+     * 实际上,会拼接属性配置(环境变量 + properties 属性)到 ProviderConfig 对象。
+     */
     private void checkDefault() {
         if (provider == null) {
             provider = new ProviderConfig();
@@ -692,15 +883,21 @@ private void checkDefault() {
         appendProperties(provider);
     }
 
+    /**
+     * 校验 ProtocolConfig 配置数组。
+     * 实际上,会拼接属性配置(环境变量 + properties 属性)到 ProtocolConfig 对象数组。
+     */
     private void checkProtocol() {
+        // 当 ProtocolConfig 对象数组为空时,优先使用 `ProviderConfig.protocols` 。其次,进行创建。
         if ((protocols == null || protocols.isEmpty())
                 && provider != null) {
             setProtocols(provider.getProtocols());
         }
-        // backward compatibility
+        // backward compatibility 向后兼容
         if (protocols == null || protocols.isEmpty()) {
             setProtocol(new ProtocolConfig());
         }
+        // 拼接属性配置(环境变量 + properties 属性)到 ProtocolConfig 对象数组
         for (ProtocolConfig protocolConfig : protocols) {
             if (StringUtils.isEmpty(protocolConfig.getName())) {
                 protocolConfig.setName("dubbo");
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/invoker/DelegateProviderMetaDataInvoker.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/invoker/DelegateProviderMetaDataInvoker.java
index 14bfa50215..96378fc491 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/invoker/DelegateProviderMetaDataInvoker.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/invoker/DelegateProviderMetaDataInvoker.java
@@ -24,7 +24,14 @@
 import com.alibaba.dubbo.rpc.RpcException;
 
 public class DelegateProviderMetaDataInvoker<T> implements Invoker {
+
+    /**
+     * Invoker 对象
+     */
     protected final Invoker<T> invoker;
+    /**
+     * 服务提供者配置
+     */
     private ServiceConfig metadata;
 
     public DelegateProviderMetaDataInvoker(Invoker<T> invoker,ServiceConfig metadata) {
@@ -44,6 +51,7 @@ public boolean isAvailable() {
         return invoker.isAvailable();
     }
 
+    @Override
     public Result invoke(Invocation invocation) throws RpcException {
         return invoker.invoke(invocation);
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/model/ProviderModel.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/model/ProviderModel.java
index 1dbe988f39..b8fdc4fd54 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/model/ProviderModel.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/model/ProviderModel.java
@@ -77,7 +77,7 @@ public ProviderMethodModel getMethodModel(String methodName, String[] argTypes)
     }
 
     private void initMethod() {
-        Method[] methodsToExport = null;
+        Method[] methodsToExport;
         methodsToExport = metadata.getInterfaceClass().getMethods();
 
         for (Method method : methodsToExport) {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/support/Parameter.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/support/Parameter.java
index 9a392d305e..04f7ef19a3 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/support/Parameter.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/support/Parameter.java
@@ -16,30 +16,74 @@
  */
 package com.alibaba.dubbo.config.support;
 
+import com.alibaba.dubbo.config.AbstractInterfaceConfig;
+import com.alibaba.dubbo.config.AbstractReferenceConfig;
+import com.alibaba.dubbo.config.AbstractServiceConfig;
+
 import java.lang.annotation.Documented;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
+import java.util.Map;
 
 /**
- * Parameter
+ * Parameter 参数
+ *
+ * 用于 Dubbo {@link com.alibaba.dubbo.common.URL} 的参数拼接
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD})
 public @interface Parameter {
 
+    /**
+     * 键(别名)
+     */
     String key() default "";
 
+    /**
+     * 是否必填
+     */
     boolean required() default false;
 
+    /**
+     * 是否忽略
+     */
     boolean excluded() default false;
 
+    /**
+     * 是否转义
+     */
     boolean escaped() default false;
 
+    /**
+     * 是否为属性
+     *
+     * 目前用于《事件通知》http://dubbo.io/books/dubbo-user-book/demos/events-notify.html
+     */
     boolean attribute() default false;
 
+    /**
+     * 是否拼接默认属性,参见 {@link com.alibaba.dubbo.config.AbstractConfig#appendParameters(Map, Object, String)} 方法。
+     *
+     * 我们来看看 `#append() = true` 的属性,有如下四个:
+     *   + {@link AbstractInterfaceConfig#getFilter()}
+     *   + {@link AbstractInterfaceConfig#getListener()}
+     *   + {@link AbstractReferenceConfig#getFilter()}
+     *   + {@link AbstractReferenceConfig#getListener()}
+     *   + {@link AbstractServiceConfig#getFilter()}
+     *   + {@link AbstractServiceConfig#getListener()}
+     * 那么,以 AbstractServiceConfig 举例子。
+     *
+     * 我们知道 ProviderConfig 和 ServiceConfig 继承 AbstractServiceConfig 类,那么 `filter` , `listener` 对应的相同的键。
+     * 下面我们以 `filter` 举例子。
+     *
+     * 在 ServiceConfig 中,默认会<b>继承</b> ProviderConfig 配置的 `filter` 和 `listener` 。
+     * 所以这个属性,就是用于,像 ServiceConfig 的这种情况,从 ProviderConfig 读取父属性。
+     *
+     * 举个例子,如果 `ProviderConfig.filter=aaaFilter` ,`ServiceConfig.filter=bbbFilter` ,最终暴露到 Dubbo URL 时,参数为 `service.filter=aaaFilter,bbbFilter` 。
+     */
     boolean append() default false;
 
 }
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ReferenceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ReferenceBean.java
index f3aa9b0249..e6e48a41ac 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ReferenceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ReferenceBean.java
@@ -61,10 +61,12 @@ public void setApplicationContext(ApplicationContext applicationContext) {
         SpringExtensionFactory.addApplicationContext(applicationContext);
     }
 
+    @Override
     public Object getObject() throws Exception {
         return get();
     }
 
+    @Override
     public Class<?> getObjectType() {
         return getInterfaceClass();
     }
@@ -74,6 +76,7 @@ public boolean isSingleton() {
         return true;
     }
 
+    @Override
     @SuppressWarnings({"unchecked"})
     public void afterPropertiesSet() throws Exception {
         if (getConsumer() == null) {
@@ -168,7 +171,7 @@ public void afterPropertiesSet() throws Exception {
         if (b == null && getConsumer() != null) {
             b = getConsumer().isInit();
         }
-        if (b != null && b.booleanValue()) {
+        if (b != null && b) {
             getObject();
         }
     }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java
index 2e614efdb6..a149cc9404 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java
@@ -131,6 +131,7 @@ private boolean isDelay() {
         return supportedApplicationListener && (delay == null || delay == -1);
     }
 
+    @Override
     @SuppressWarnings({"unchecked", "deprecation"})
     public void afterPropertiesSet() throws Exception {
         if (getProvider() == null) {
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java
index e59e5e4e25..b433c3c1a9 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java
@@ -76,7 +76,6 @@ public ServiceAnnotationBeanPostProcessor(Set<String> packagesToScan) {
 
     @Override
     public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
-
         Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
 
         if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
@@ -86,10 +85,8 @@ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) t
                 logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
             }
         }
-
     }
 
-
     /**
      * Registers Beans whose classes was annotated {@link Service}
      *
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java
index 3d13de4651..926d1cb0fc 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java
@@ -27,6 +27,9 @@
  */
 public class SpringExtensionFactory implements ExtensionFactory {
 
+    /**
+     * Spring Context 集合
+     */
     private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>();
 
     public static void addApplicationContext(ApplicationContext context) {
@@ -37,11 +40,14 @@ public static void removeApplicationContext(ApplicationContext context) {
         contexts.remove(context);
     }
 
+    @Override
     @SuppressWarnings("unchecked")
     public <T> T getExtension(Class<T> type, String name) {
         for (ApplicationContext context : contexts) {
             if (context.containsBean(name)) {
+                // 获得属性
                 Object bean = context.getBean(name);
+                // 判断类型
                 if (type.isInstance(bean)) {
                     return (T) bean;
                 }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboBeanDefinitionParser.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
index e6d386fc03..b2e1f82176 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
@@ -56,8 +56,16 @@
 public class DubboBeanDefinitionParser implements BeanDefinitionParser {
 
     private static final Logger logger = LoggerFactory.getLogger(DubboBeanDefinitionParser.class);
-    private static final Pattern GROUP_AND_VERION = Pattern.compile("^[\\-.0-9_a-zA-Z]+(\\:[\\-.0-9_a-zA-Z]+)?$");
+
+    private static final Pattern GROUP_AND_VERION = Pattern.compile("^[\\-.0-9_a-zA-Z]+(\\:[\\-.0-9_a-zA-Z]+)?$"); // 暂未使用
+
+    /**
+     * Bean 对象的类
+     */
     private final Class<?> beanClass;
+    /**
+     * 是否需要 Bean 的 `id` 属性
+     */
     private final boolean required;
 
     public DubboBeanDefinitionParser(Class<?> beanClass, boolean required) {
@@ -70,8 +78,10 @@ private static BeanDefinition parse(Element element, ParserContext parserContext
         RootBeanDefinition beanDefinition = new RootBeanDefinition();
         beanDefinition.setBeanClass(beanClass);
         beanDefinition.setLazyInit(false);
+        // 解析配置对象的 id 。若不存在,则进行生成。
         String id = element.getAttribute("id");
         if ((id == null || id.length() == 0) && required) {
+            // 生成 id 。不同的配置对象,会存在不同。
             String generatedBeanName = element.getAttribute("name");
             if (generatedBeanName == null || generatedBeanName.length() == 0) {
                 if (ProtocolConfig.class.equals(beanClass)) {
@@ -84,6 +94,7 @@ private static BeanDefinition parse(Element element, ParserContext parserContext
                 generatedBeanName = beanClass.getName();
             }
             id = generatedBeanName;
+            // 若 id 已存在,通过自增序列,解决重复。
             int counter = 2;
             while (parserContext.getRegistry().containsBeanDefinition(id)) {
                 id = generatedBeanName + (counter++);
@@ -93,10 +104,18 @@ private static BeanDefinition parse(Element element, ParserContext parserContext
             if (parserContext.getRegistry().containsBeanDefinition(id)) {
                 throw new IllegalStateException("Duplicate spring bean id " + id);
             }
+            // 添加到 Spring 的注册表
             parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
+            // 设置 Bean 的 `id` 属性值
             beanDefinition.getPropertyValues().addPropertyValue("id", id);
         }
+//        System.out.println("id:" + id);
+        // 处理 `<dubbo:protocol` /> 的特殊情况
         if (ProtocolConfig.class.equals(beanClass)) {
+            // 需要满足第 220 至 233 行。
+            // 例如:【顺序要这样】
+            // <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" protocol="dubbo" ref="demoService"/>
+            // <dubbo:protocol id="dubbo" name="dubbo" port="20880"/>
             for (String name : parserContext.getRegistry().getBeanDefinitionNames()) {
                 BeanDefinition definition = parserContext.getRegistry().getBeanDefinition(name);
                 PropertyValue property = definition.getPropertyValues().getPropertyValue("protocol");
@@ -107,30 +126,40 @@ private static BeanDefinition parse(Element element, ParserContext parserContext
                     }
                 }
             }
+        // 处理 `<dubbo:service />` 的属性 `class`
         } else if (ServiceBean.class.equals(beanClass)) {
+            // 处理 `class` 属性。例如  <dubbo:service id="sa" interface="com.alibaba.dubbo.demo.DemoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" >
             String className = element.getAttribute("class");
             if (className != null && className.length() > 0) {
+                // 创建 Service 的 RootBeanDefinition 对象。相当于内嵌了 <bean class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" />
                 RootBeanDefinition classDefinition = new RootBeanDefinition();
                 classDefinition.setBeanClass(ReflectUtils.forName(className));
                 classDefinition.setLazyInit(false);
+                // 解析 Service Bean 对象的属性
                 parseProperties(element.getChildNodes(), classDefinition);
+                // 设置 `<dubbo:service ref="" />` 属性
                 beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
             }
+        // 解析 `<dubbo:provider />` 的内嵌子元素 `<dubbo:service />`
         } else if (ProviderConfig.class.equals(beanClass)) {
             parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);
+        // 解析 `<dubbo:consumer />` 的内嵌子元素 `<dubbo:reference />`
         } else if (ConsumerConfig.class.equals(beanClass)) {
             parseNested(element, parserContext, ReferenceBean.class, false, "reference", "consumer", id, beanDefinition);
         }
-        Set<String> props = new HashSet<String>();
-        ManagedMap parameters = null;
+        Set<String> props = new HashSet<String>(); // 已解析的属性集合
+        ManagedMap parameters = null; //
+        // 循环 Bean 对象的 setting 方法,将属性添加到 Bean 对象的属性赋值
         for (Method setter : beanClass.getMethods()) {
             String name = setter.getName();
             if (name.length() > 3 && name.startsWith("set")
                     && Modifier.isPublic(setter.getModifiers())
-                    && setter.getParameterTypes().length == 1) {
+                    && setter.getParameterTypes().length == 1) { // setting && public && 唯一参数
                 Class<?> type = setter.getParameterTypes()[0];
+                // 添加 `props`
                 String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), "-");
                 props.add(property);
+                // getting && public && 属性值类型统一
                 Method getter = null;
                 try {
                     getter = beanClass.getMethod("get" + name.substring(3), new Class<?>[0]);
@@ -145,10 +174,13 @@ private static BeanDefinition parse(Element element, ParserContext parserContext
                         || !type.equals(getter.getReturnType())) {
                     continue;
                 }
+                // 解析 `<dubbo:parameters />`
                 if ("parameters".equals(property)) {
                     parameters = parseParameters(element.getChildNodes(), beanDefinition);
+                // 解析 `<dubbo:method />`
                 } else if ("methods".equals(property)) {
                     parseMethods(id, element.getChildNodes(), beanDefinition, parserContext);
+                // 解析 `<dubbo:argument />`
                 } else if ("arguments".equals(property)) {
                     parseArguments(id, element.getChildNodes(), beanDefinition, parserContext);
                 } else {
@@ -156,19 +188,25 @@ private static BeanDefinition parse(Element element, ParserContext parserContext
                     if (value != null) {
                         value = value.trim();
                         if (value.length() > 0) {
+                            // 不想注册到注册中心的情况,即 `registry=N/A` 。
                             if ("registry".equals(property) && RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(value)) {
                                 RegistryConfig registryConfig = new RegistryConfig();
                                 registryConfig.setAddress(RegistryConfig.NO_AVAILABLE);
                                 beanDefinition.getPropertyValues().addPropertyValue(property, registryConfig);
+                            // 多注册中心的情况
                             } else if ("registry".equals(property) && value.indexOf(',') != -1) {
                                 parseMultiRef("registries", value, beanDefinition, parserContext);
+                            // 多服务提供者的情况
                             } else if ("provider".equals(property) && value.indexOf(',') != -1) {
                                 parseMultiRef("providers", value, beanDefinition, parserContext);
+                            // 多协议的情况
                             } else if ("protocol".equals(property) && value.indexOf(',') != -1) {
                                 parseMultiRef("protocols", value, beanDefinition, parserContext);
                             } else {
                                 Object reference;
+                                // 处理属性类型为基本属性的情况
                                 if (isPrimitive(type)) {
+                                    // 兼容性处理
                                     if ("async".equals(property) && "false".equals(value)
                                             || "timeout".equals(property) && "0".equals(value)
                                             || "delay".equals(property) && "0".equals(value)
@@ -179,10 +217,13 @@ private static BeanDefinition parse(Element element, ParserContext parserContext
                                         value = null;
                                     }
                                     reference = value;
+                                // 处理在 `<dubbo:provider />` 或者 `<dubbo:service />` 上定义了 `protocol` 属性的 兼容性。
                                 } else if ("protocol".equals(property)
-                                        && ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(value)
-                                        && (!parserContext.getRegistry().containsBeanDefinition(value)
-                                        || !ProtocolConfig.class.getName().equals(parserContext.getRegistry().getBeanDefinition(value).getBeanClassName()))) {
+                                        && ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(value) // 存在该注册协议的实现
+                                        && (!parserContext.getRegistry().containsBeanDefinition(value) // Spring 注册表中不存在该 `<dubbo:provider />` 的定义
+                                            || !ProtocolConfig.class.getName().equals(parserContext.getRegistry().getBeanDefinition(value).getBeanClassName())) // Spring 注册表中存在该编号,但是类型不为 ProtocolConfig 。
+                                        ) {
+                                    // 目前,`<dubbo:provider protocol="" />` 推荐独立成 `<dubbo:protocol />`
                                     if ("dubbo:provider".equals(element.getTagName())) {
                                         logger.warn("Recommended replace <dubbo:provider protocol=\"" + value + "\" ... /> to <dubbo:protocol name=\"" + value + "\" ... />");
                                     }
@@ -190,27 +231,39 @@ private static BeanDefinition parse(Element element, ParserContext parserContext
                                     ProtocolConfig protocol = new ProtocolConfig();
                                     protocol.setName(value);
                                     reference = protocol;
+                                // 处理 `onreturn` 属性
                                 } else if ("onreturn".equals(property)) {
+                                    // 按照 `.` 拆分
                                     int index = value.lastIndexOf(".");
                                     String returnRef = value.substring(0, index);
                                     String returnMethod = value.substring(index + 1);
+                                    // 创建 RuntimeBeanReference ,指向回调的对象
                                     reference = new RuntimeBeanReference(returnRef);
+                                    // 设置 `onreturnMethod` 到 BeanDefinition 的属性值
                                     beanDefinition.getPropertyValues().addPropertyValue("onreturnMethod", returnMethod);
+                                    // 处理 `onthrow` 属性
                                 } else if ("onthrow".equals(property)) {
+                                    // 按照 `.` 拆分
                                     int index = value.lastIndexOf(".");
                                     String throwRef = value.substring(0, index);
                                     String throwMethod = value.substring(index + 1);
+                                    // 创建 RuntimeBeanReference ,指向回调的对象
                                     reference = new RuntimeBeanReference(throwRef);
+                                    // 设置 `onthrowMethod` 到 BeanDefinition 的属性值
                                     beanDefinition.getPropertyValues().addPropertyValue("onthrowMethod", throwMethod);
+                                // 通用解析
                                 } else {
+                                    // 指向的 Service 的 Bean 对象,必须是单例
                                     if ("ref".equals(property) && parserContext.getRegistry().containsBeanDefinition(value)) {
                                         BeanDefinition refBean = parserContext.getRegistry().getBeanDefinition(value);
                                         if (!refBean.isSingleton()) {
                                             throw new IllegalStateException("The exported service ref " + value + " must be singleton! Please set the " + value + " bean scope to singleton, eg: <bean id=\"" + value + "\" scope=\"singleton\" ...>");
                                         }
                                     }
+                                    // 创建 RuntimeBeanReference ,指向 Service 的 Bean 对象
                                     reference = new RuntimeBeanReference(value);
                                 }
+                                // 设置 BeanDefinition 的属性值
                                 beanDefinition.getPropertyValues().addPropertyValue(property, reference);
                             }
                         }
@@ -218,6 +271,7 @@ private static BeanDefinition parse(Element element, ParserContext parserContext
                 }
             }
         }
+        // 将 XML 元素,未在上面遍历到的属性,添加到 `parameters` 集合中。目前测试下来,不存在这样的情况。
         NamedNodeMap attributes = element.getAttributes();
         int len = attributes.getLength();
         for (int i = 0; i < len; i++) {
@@ -244,6 +298,14 @@ private static boolean isPrimitive(Class<?> cls) {
                 || cls == String.class || cls == Date.class || cls == Class.class;
     }
 
+    /**
+     * 解析多指向的情况,例如多注册中心,多协议等等。
+     *
+     * @param property 属性
+     * @param value 值
+     * @param beanDefinition Bean 定义对象
+     * @param parserContext Spring 解析上下文
+     */
     @SuppressWarnings("unchecked")
     private static void parseMultiRef(String property, String value, RootBeanDefinition beanDefinition,
                                       ParserContext parserContext) {
@@ -261,7 +323,20 @@ private static void parseMultiRef(String property, String value, RootBeanDefinit
         beanDefinition.getPropertyValues().addPropertyValue(property, list);
     }
 
-    private static void parseNested(Element element, ParserContext parserContext, Class<?> beanClass, boolean required, String tag, String property, String ref, BeanDefinition beanDefinition) {
+    /**
+     * 解析内嵌的指向的子 XML 元素
+     *
+     * @param element 父 XML 元素
+     * @param parserContext Spring 解析上下文
+     * @param beanClass 内嵌解析子元素的 Bean 的类
+     * @param required 是否需要 Bean 的 `id` 属性
+     * @param tag 标签
+     * @param property 父 Bean 对象在子元素中的属性名
+     * @param ref 指向
+     * @param beanDefinition 父 Bean 定义对象
+     */
+    private static void parseNested(Element element, ParserContext parserContext, Class<?> beanClass, boolean required, String tag,
+                                    String property, String ref, BeanDefinition beanDefinition) {
         NodeList nodeList = element.getChildNodes();
         if (nodeList != null && nodeList.getLength() > 0) {
             boolean first = true;
@@ -269,7 +344,8 @@ private static void parseNested(Element element, ParserContext parserContext, Cl
                 Node node = nodeList.item(i);
                 if (node instanceof Element) {
                     if (tag.equals(node.getNodeName())
-                            || tag.equals(node.getLocalName())) {
+                            || tag.equals(node.getLocalName())) { // 这三行,判断是否为指定要解析的子元素
+                        // 【TODO 8008】 芋艿,default 是干锤子的
                         if (first) {
                             first = false;
                             String isDefault = element.getAttribute("default");
@@ -277,7 +353,9 @@ private static void parseNested(Element element, ParserContext parserContext, Cl
                                 beanDefinition.getPropertyValues().addPropertyValue("default", "false");
                             }
                         }
+                        // 解析子元素,创建 BeanDefinition 对象
                         BeanDefinition subDefinition = parse((Element) node, parserContext, beanClass, required);
+                        // 设置子 BeanDefinition ,指向父 BeanDefinition 。
                         if (subDefinition != null && ref != null && ref.length() > 0) {
                             subDefinition.getPropertyValues().addPropertyValue(property, new RuntimeBeanReference(ref));
                         }
@@ -287,6 +365,12 @@ private static void parseNested(Element element, ParserContext parserContext, Cl
         }
     }
 
+    /**
+     * 解析 <dubbo:service class="" /> 情况下,内涵的 `<property />` 的赋值。
+     *
+     * @param nodeList 子元素数组
+     * @param beanDefinition Bean 定义对象
+     */
     private static void parseProperties(NodeList nodeList, RootBeanDefinition beanDefinition) {
         if (nodeList != null && nodeList.getLength() > 0) {
             for (int i = 0; i < nodeList.getLength(); i++) {
@@ -298,8 +382,10 @@ private static void parseProperties(NodeList nodeList, RootBeanDefinition beanDe
                         if (name != null && name.length() > 0) {
                             String value = ((Element) node).getAttribute("value");
                             String ref = ((Element) node).getAttribute("ref");
+                            // value
                             if (value != null && value.length() > 0) {
                                 beanDefinition.getPropertyValues().addPropertyValue(name, value);
+                            // ref
                             } else if (ref != null && ref.length() > 0) {
                                 beanDefinition.getPropertyValues().addPropertyValue(name, new RuntimeBeanReference(ref));
                             } else {
@@ -312,6 +398,13 @@ private static void parseProperties(NodeList nodeList, RootBeanDefinition beanDe
         }
     }
 
+    /**
+     * 解析 `<dubbo:parameter />`
+     *
+     * @param nodeList 子元素节点数组
+     * @param beanDefinition Bean 定义对象
+     * @return 参数集合
+     */
     @SuppressWarnings("unchecked")
     private static ManagedMap parseParameters(NodeList nodeList, RootBeanDefinition beanDefinition) {
         if (nodeList != null && nodeList.getLength() > 0) {
@@ -320,13 +413,14 @@ private static ManagedMap parseParameters(NodeList nodeList, RootBeanDefinition
                 Node node = nodeList.item(i);
                 if (node instanceof Element) {
                     if ("parameter".equals(node.getNodeName())
-                            || "parameter".equals(node.getLocalName())) {
+                            || "parameter".equals(node.getLocalName())) { // 这三行,只解析子元素中的 `<dubbo:parameter />`
                         if (parameters == null) {
                             parameters = new ManagedMap();
                         }
+                        // 添加到参数集合
                         String key = ((Element) node).getAttribute("key");
                         String value = ((Element) node).getAttribute("value");
-                        boolean hide = "true".equals(((Element) node).getAttribute("hide"));
+                        boolean hide = "true".equals(((Element) node).getAttribute("hide")); // 【TODO 8007】 <dubbo:parameter hide=“” /> 的用途
                         if (hide) {
                             key = Constants.HIDE_KEY_PREFIX + key;
                         }
@@ -339,16 +433,26 @@ private static ManagedMap parseParameters(NodeList nodeList, RootBeanDefinition
         return null;
     }
 
+    /**
+     * 解析 `<dubbo:method />`
+     *
+     * @param id Bean 的 `id` 属性。
+     * @param nodeList 子元素节点数组
+     * @param beanDefinition Bean 定义对象
+     * @param parserContext 解析上下文
+     */
     @SuppressWarnings("unchecked")
     private static void parseMethods(String id, NodeList nodeList, RootBeanDefinition beanDefinition,
                                      ParserContext parserContext) {
         if (nodeList != null && nodeList.getLength() > 0) {
-            ManagedList methods = null;
+            ManagedList methods = null; // 解析的方法数组
             for (int i = 0; i < nodeList.getLength(); i++) {
                 Node node = nodeList.item(i);
                 if (node instanceof Element) {
                     Element element = (Element) node;
-                    if ("method".equals(node.getNodeName()) || "method".equals(node.getLocalName())) {
+                    if ("method".equals(node.getNodeName())
+                            || "method".equals(node.getLocalName())) { // 这三行,判断值解析 `<dubbo:method />`
+                        // 方法名不能为空
                         String methodName = element.getAttribute("name");
                         if (methodName == null || methodName.length() == 0) {
                             throw new IllegalStateException("<dubbo:method> name attribute == null");
@@ -356,11 +460,11 @@ private static void parseMethods(String id, NodeList nodeList, RootBeanDefinitio
                         if (methods == null) {
                             methods = new ManagedList();
                         }
-                        BeanDefinition methodBeanDefinition = parse(((Element) node),
-                                parserContext, MethodConfig.class, false);
+                        // 解析 `<dubbo:method />`,创建 BeanDefinition 对象
+                        BeanDefinition methodBeanDefinition = parse(((Element) node), parserContext, MethodConfig.class, false);
+                        // 添加到 `methods` 中
                         String name = id + "." + methodName;
-                        BeanDefinitionHolder methodBeanDefinitionHolder = new BeanDefinitionHolder(
-                                methodBeanDefinition, name);
+                        BeanDefinitionHolder methodBeanDefinitionHolder = new BeanDefinitionHolder(methodBeanDefinition, name);
                         methods.add(methodBeanDefinitionHolder);
                     }
                 }
@@ -371,25 +475,34 @@ private static void parseMethods(String id, NodeList nodeList, RootBeanDefinitio
         }
     }
 
+    /**
+     * 解析 `<dubbo:argument />`
+     *
+     * @param id Bean 的 `id` 属性。
+     * @param nodeList 子元素节点数组
+     * @param beanDefinition Bean 定义对象
+     * @param parserContext 解析上下文
+     */
     @SuppressWarnings("unchecked")
     private static void parseArguments(String id, NodeList nodeList, RootBeanDefinition beanDefinition,
                                        ParserContext parserContext) {
         if (nodeList != null && nodeList.getLength() > 0) {
-            ManagedList arguments = null;
+            ManagedList arguments = null; // 解析的参数数组
             for (int i = 0; i < nodeList.getLength(); i++) {
                 Node node = nodeList.item(i);
                 if (node instanceof Element) {
                     Element element = (Element) node;
-                    if ("argument".equals(node.getNodeName()) || "argument".equals(node.getLocalName())) {
+                    if ("argument".equals(node.getNodeName())
+                            || "argument".equals(node.getLocalName())) { // 这三行,判断值解析 `<dubbo:argument />`
                         String argumentIndex = element.getAttribute("index");
                         if (arguments == null) {
                             arguments = new ManagedList();
                         }
-                        BeanDefinition argumentBeanDefinition = parse(((Element) node),
-                                parserContext, ArgumentConfig.class, false);
+                        // 解析 `<dubbo:argument />`,创建 BeanDefinition 对象
+                        BeanDefinition argumentBeanDefinition = parse(((Element) node), parserContext, ArgumentConfig.class, false);
+                        // 添加到 `arguments` 中
                         String name = id + "." + argumentIndex;
-                        BeanDefinitionHolder argumentBeanDefinitionHolder = new BeanDefinitionHolder(
-                                argumentBeanDefinition, name);
+                        BeanDefinitionHolder argumentBeanDefinitionHolder = new BeanDefinitionHolder(argumentBeanDefinition, name);
                         arguments.add(argumentBeanDefinitionHolder);
                     }
                 }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboNamespaceHandler.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboNamespaceHandler.java
index da44826514..aa56d4f3f2 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboNamespaceHandler.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboNamespaceHandler.java
@@ -33,6 +33,7 @@
         Version.checkDuplicate(DubboNamespaceHandler.class);
     }
 
+    @Override
     public void init() {
         registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
         registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
@@ -43,7 +44,8 @@ public void init() {
         registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
         registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
         registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
-        registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
+
+        registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser()); // 废弃
     }
 
 }
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/Cat.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/Cat.java
new file mode 100644
index 0000000000..d7439c2f62
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/Cat.java
@@ -0,0 +1,24 @@
+package com.alibaba.dubbo.demo;
+
+import java.io.Serializable;
+
+/**
+ * 猫
+ */
+public class Cat implements Serializable {
+
+    /**
+     * 名字
+     */
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public Cat setName(String name) {
+        this.name = name;
+        return this;
+    }
+
+}
diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java
index 6369c9785a..0336ddd201 100644
--- a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java
+++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java
@@ -20,4 +20,16 @@
 
     String sayHello(String name);
 
+    void bye(Object o);
+
+    void callbackParam(String msg, ParamCallback callback);
+
+    String say01(String msg);
+
+    String[] say02();
+
+    void say03();
+
+    Void say04();
+
 }
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/Dog.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/Dog.java
new file mode 100644
index 0000000000..5894ce90d3
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/Dog.java
@@ -0,0 +1,18 @@
+package com.alibaba.dubbo.demo;
+
+import java.io.Serializable;
+
+public class Dog implements Serializable {
+
+    private Integer age;
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public Dog setAge(Integer age) {
+        this.age = age;
+        return this;
+    }
+
+}
diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/HttpDemoService.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/HttpDemoService.java
new file mode 100644
index 0000000000..35579fa62a
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/HttpDemoService.java
@@ -0,0 +1,7 @@
+package com.alibaba.dubbo.demo;
+
+public interface HttpDemoService {
+
+    String hello(String msg);
+
+}
diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/ParamCallback.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/ParamCallback.java
new file mode 100644
index 0000000000..f10fbc4253
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/ParamCallback.java
@@ -0,0 +1,10 @@
+package com.alibaba.dubbo.demo;
+
+/**
+ * https://dubbo.gitbooks.io/dubbo-user-book/demos/callback-parameter.html
+ */
+public interface ParamCallback {
+
+    void doSome(Cat msg);
+
+}
diff --git a/dubbo-demo/dubbo-demo-consumer/pom.xml b/dubbo-demo/dubbo-demo-consumer/pom.xml
index 832f7f372d..d1bf739f64 100644
--- a/dubbo-demo/dubbo-demo-consumer/pom.xml
+++ b/dubbo-demo/dubbo-demo-consumer/pom.xml
@@ -57,7 +57,8 @@ limitations under the License.
         </dependency>
         <dependency>
             <groupId>com.alibaba</groupId>
-            <artifactId>dubbo-remoting-netty</artifactId>
+            <!--<artifactId>dubbo-remoting-netty</artifactId>-->
+            <artifactId>dubbo-remoting-netty4</artifactId>
         </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/Consumer.java b/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/Consumer.java
index 9caacbc7ad..43b5b1de2d 100644
--- a/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/Consumer.java
+++ b/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/Consumer.java
@@ -32,8 +32,32 @@ public static void main(String[] args) {
         while (true) {
             try {
                 Thread.sleep(1000);
-                String hello = demoService.sayHello("world"); // call remote method
-                System.out.println(hello); // get result
+//                try {
+//                    demoService.sayHello(gen(1024000));
+//                } catch (Exception e) {
+//                }
+
+//                String hello = demoService.sayHello("world"); // call remote method
+//                System.out.println(hello); // get result
+
+
+                demoService.say01(null);
+                demoService.say01("hahha");
+                demoService.say02();
+                demoService.say03();
+                demoService.say04();
+
+                // 参数回调
+                // https://dubbo.gitbooks.io/dubbo-user-book/demos/callback-parameter.html
+//                demoService.callbackParam("shuaiqi", new ParamCallback() {
+//                    @Override
+//                    public void doSome(Cat msg) {
+//                        System.out.println("回调biubiu:" + msg);
+//                    }
+//                });
+
+//                demoService.bye(new Cat().setName("小猫"));
+//                demoService.bye(new Dog().setAge(10));
 
             } catch (Throwable throwable) {
                 throwable.printStackTrace();
@@ -43,4 +67,12 @@ public static void main(String[] args) {
         }
 
     }
+
+    private static String gen(int len) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < len; i++) {
+            sb.append("s");
+        }
+        return sb.toString();
+    }
 }
diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/callback/CallbackImpl.java b/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/callback/CallbackImpl.java
new file mode 100644
index 0000000000..288b12f278
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/callback/CallbackImpl.java
@@ -0,0 +1,13 @@
+package com.alibaba.dubbo.demo.consumer.callback;
+
+public class CallbackImpl {
+
+    public void done(String result) {
+        System.out.println("结果:" + result);
+    }
+
+    public void handleException(Throwable e) {
+        System.out.println("异常:" + e.getMessage());
+    }
+
+}
diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
index 578418e5c1..4fba6d757d 100644
--- a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
+++ b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
@@ -1,35 +1,48 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
-       xmlns="http://www.springframework.org/schema/beans"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
-
-    <!-- consumer's application name, used for tracing dependency relationship (not a matching criterion),
-    don't set it same as provider -->
-    <dubbo:application name="demo-consumer"/>
-
-    <!-- use multicast registry center to discover service -->
-    <dubbo:registry address="multicast://224.5.6.7:1234"/>
-
-    <!-- generate proxy for the remote service, then demoService can be used in the same way as the
-    local regular interface -->
-    <dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService"/>
-
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
+       xmlns="http://www.springframework.org/schema/beans"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
+
+    <bean id="callbackDemo" class="com.alibaba.dubbo.demo.consumer.callback.CallbackImpl" />
+
+    <!-- consumer's application name, used for tracing dependency relationship (not a matching criterion),
+    don't set it same as provider -->
+    <dubbo:application name="demo-consumer" />
+
+    <!-- use multicast registry center to discover service -->
+    <!--<dubbo:registry address="multicast://224.5.6.7:1234"/>-->
+    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
+
+    <!-- generate proxy for the remote service, then demoService can be used in the same way as the
+    local regular interface -->
+    <dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService" client="netty4" timeout="100000" callbacks="1000">
+        <!--<dubbo:method name="sayHello" />-->
+
+        <!--url="registry://127.0.0.1:2181?registry=zookeeper;127.0.0.1:2181;127.0.0.1:27018"-->
+        
+        <dubbo:parameter key="payload" value="1000" />
+        
+        <dubbo:method name="sayHello" async="true" onreturn="callbackDemo.done" />
+        
+    </dubbo:reference>
+
+
 </beans>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-injvm/pom.xml b/dubbo-demo/dubbo-demo-injvm/pom.xml
new file mode 100644
index 0000000000..5a0bba4a1d
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-injvm/pom.xml
@@ -0,0 +1,63 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.alibaba</groupId>
+        <artifactId>dubbo-demo</artifactId>
+        <version>2.6.1</version>
+    </parent>
+    <artifactId>dubbo-demo-injvm</artifactId>
+    <packaging>jar</packaging>
+    <name>${project.artifactId}</name>
+    <description>The demo consumer module of dubbo project</description>
+    <properties>
+        <skip_maven_deploy>true</skip_maven_deploy>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-demo-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-config-spring</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-registry-zookeeper</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-registry-multicast</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-cluster</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-rpc-default</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-remoting-netty</artifactId>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-injvm/src/main/java/com/alibaba/dubbo/demo/consumer/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-injvm/src/main/java/com/alibaba/dubbo/demo/consumer/DemoServiceImpl.java
new file mode 100644
index 0000000000..8d18160f29
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-injvm/src/main/java/com/alibaba/dubbo/demo/consumer/DemoServiceImpl.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.demo.consumer;
+
+import com.alibaba.dubbo.demo.DemoService;
+import com.alibaba.dubbo.rpc.RpcContext;
+import com.alibaba.fastjson.JSON;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DemoServiceImpl implements DemoService {
+
+    public String sayHello(String name) {
+        System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
+        return "localhost: Hello " + name + ", response form provider: " + RpcContext.getContext().getLocalAddress();
+    }
+
+    @Override
+    public void bye(Object o) {
+        System.out.println(JSON.toJSONString(o));
+        System.out.println(o.getClass());
+    }
+
+//    public String getTest01() {
+//        return test01;
+//    }
+//
+//    public DemoServiceImpl setTest01(String test01) {
+//        this.test01 = test01;
+//        return this;
+//    }
+
+    //    public void setTest01(String test01) {
+//        this.test01 = test01;
+//    }
+
+}
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-injvm/src/main/java/com/alibaba/dubbo/demo/consumer/InjvmConsumer.java b/dubbo-demo/dubbo-demo-injvm/src/main/java/com/alibaba/dubbo/demo/consumer/InjvmConsumer.java
new file mode 100644
index 0000000000..cb2beb51f5
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-injvm/src/main/java/com/alibaba/dubbo/demo/consumer/InjvmConsumer.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.demo.consumer;
+
+import com.alibaba.dubbo.demo.DemoService;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class InjvmConsumer {
+
+    public static void main(String[] args) {
+        //Prevent to get IPV6 address,this way only work in debug mode
+        //But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
+        System.setProperty("java.net.preferIPv4Stack", "true");
+        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-injvm.xml"});
+        context.start();
+        DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy
+
+        while (true) {
+            try {
+                Thread.sleep(1000);
+                String hello = demoService.sayHello("world"); // call remote method
+                System.out.println(hello); // get result
+
+//                demoService.bye(new Cat().setName("小猫"));
+//                demoService.bye(new Dog().setAge(10));
+
+            } catch (Throwable throwable) {
+                throwable.printStackTrace();
+            }
+
+
+        }
+
+    }
+}
diff --git a/dubbo-demo/dubbo-demo-injvm/src/main/resources/META-INF/spring/dubbo-demo-injvm.xml b/dubbo-demo/dubbo-demo-injvm/src/main/resources/META-INF/spring/dubbo-demo-injvm.xml
new file mode 100644
index 0000000000..8df9e57dbc
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-injvm/src/main/resources/META-INF/spring/dubbo-demo-injvm.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
+       xmlns="http://www.springframework.org/schema/beans"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
+
+    <dubbo:application name="demo-injvm"/>
+
+    <dubbo:registry address="N/A"/>
+
+    <dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" protocol="injvm">
+        <dubbo:parameter key="deprecated" value="true" />
+    </dubbo:reference>
+
+    <bean id="demoServiceImpl" class="com.alibaba.dubbo.demo.consumer.DemoServiceImpl"/>
+    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoServiceImpl" protocol="injvm"  />
+
+</beans>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-injvm/src/main/resources/dubbo.properties b/dubbo-demo/dubbo-demo-injvm/src/main/resources/dubbo.properties
new file mode 100644
index 0000000000..8c3cb2559c
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-injvm/src/main/resources/dubbo.properties
@@ -0,0 +1 @@
+dubbo.application.qos.port=33333
diff --git a/dubbo-demo/dubbo-demo-injvm/src/main/resources/log4j.properties b/dubbo-demo/dubbo-demo-injvm/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..63f4e27e3c
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-injvm/src/main/resources/log4j.properties
@@ -0,0 +1,7 @@
+###set log levels###
+log4j.rootLogger=info, stdout
+###output to console###
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-provider/pom.xml b/dubbo-demo/dubbo-demo-provider/pom.xml
index 05fc311f4d..58cc07da71 100644
--- a/dubbo-demo/dubbo-demo-provider/pom.xml
+++ b/dubbo-demo/dubbo-demo-provider/pom.xml
@@ -56,9 +56,13 @@ limitations under the License.
             <groupId>com.alibaba</groupId>
             <artifactId>dubbo-rpc-default</artifactId>
         </dependency>
+        <!--<dependency>-->
+            <!--<groupId>com.alibaba</groupId>-->
+            <!--<artifactId>dubbo-remoting-netty</artifactId>-->
+        <!--</dependency>-->
         <dependency>
             <groupId>com.alibaba</groupId>
-            <artifactId>dubbo-remoting-netty</artifactId>
+            <artifactId>dubbo-remoting-netty4</artifactId>
         </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoDAO.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoDAO.java
new file mode 100644
index 0000000000..ab57efc6f0
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoDAO.java
@@ -0,0 +1,4 @@
+package com.alibaba.dubbo.demo.provider;
+
+public class DemoDAO {
+}
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java
index c20dfa61d7..afb7d96460 100644
--- a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java
+++ b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java
@@ -16,17 +16,70 @@
  */
 package com.alibaba.dubbo.demo.provider;
 
+import com.alibaba.dubbo.demo.Cat;
 import com.alibaba.dubbo.demo.DemoService;
+import com.alibaba.dubbo.demo.ParamCallback;
 import com.alibaba.dubbo.rpc.RpcContext;
+import com.alibaba.fastjson.JSON;
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
 public class DemoServiceImpl implements DemoService {
 
+    /**
+     * 测试属性,{@link com.alibaba.dubbo.common.bytecode.Wrapper}
+     */
+    public String test01;
+
+    private DemoDAO demoDAO;
+
     public String sayHello(String name) {
         System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
         return "Hello " + name + ", response form provider: " + RpcContext.getContext().getLocalAddress();
     }
 
+    @Override
+    public void bye(Object o) {
+        System.out.println(JSON.toJSONString(o));
+        System.out.println(o.getClass());
+    }
+
+    @Override
+    public void callbackParam(String msg, ParamCallback callback) {
+        callback.doSome(new Cat().setName("miao"));
+    }
+
+    @Override
+    public String say01(String msg) {
+        return msg;
+    }
+
+    @Override
+    public String[] say02() {
+        return new String[0];
+    }
+
+    @Override
+    public void say03() {
+
+    }
+
+    @Override
+    public Void say04() {
+        return null;
+    }
+
+    public void setDemoDAO(DemoDAO demoDAO) {
+        this.demoDAO = demoDAO;
+    }
+
+    public void onconnect() {
+        System.out.println("连接成功");
+    }
+
+    public void ondisconnect() {
+        System.out.println("连接断开");
+    }
+
 }
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/filter/DemoFilter.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/filter/DemoFilter.java
new file mode 100644
index 0000000000..61bc67fad8
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/filter/DemoFilter.java
@@ -0,0 +1,19 @@
+package com.alibaba.dubbo.demo.provider.filter;
+
+import com.alibaba.dubbo.demo.provider.DemoDAO;
+import com.alibaba.dubbo.rpc.*;
+
+public class DemoFilter implements Filter {
+
+    private DemoDAO demoDAO;
+
+    @Override
+    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+        return invoker.invoke(invocation);
+    }
+
+    public DemoFilter setDemoDAO(DemoDAO demoDAO) {
+        this.demoDAO = demoDAO;
+        return this;
+    }
+}
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
new file mode 100644
index 0000000000..1e41a6cc96
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
@@ -0,0 +1 @@
+demo=com.alibaba.dubbo.demo.provider.filter.DemoFilter
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
index 3393dde474..92fc1e05ab 100644
--- a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
+++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
@@ -24,16 +24,52 @@ limitations under the License.
     <!-- provider's application name, used for tracing dependency relationship -->
     <dubbo:application name="demo-provider"/>
 
+    <dubbo:provider delay="-1" retries="0"  >
+        <!--<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" protocol="pb" />-->
+    </dubbo:provider>
+
     <!-- use multicast registry center to export service -->
-    <dubbo:registry address="multicast://224.5.6.7:1234"/>
+    <!--<dubbo:registry address="multicast://224.5.6.7:1234"/>-->
+    <!--<dubbo:registry address="zookeeper://127.0.0.1:2181"/>-->
+    <!--<dubbo:registry address="zookeeper://127.0.0.1:2181||10.20.153.11:2181,10.20.153.12:2181"/>-->
+    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
 
-    <!-- use dubbo protocol to export service on port 20880 -->
-    <dubbo:protocol name="dubbo" port="20880"/>
+
+    <bean id="demoDAO" class="com.alibaba.dubbo.demo.provider.DemoDAO" />
 
     <!-- service implementation, as same as regular local bean -->
     <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
 
     <!-- declare the service interface to be exported -->
-    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
+    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" filter="demo" deprecated="true" callbacks="1000" timeout="200000"
+        onconnect="onconnect" ondisconnect="ondisconnect" >
+    <!--<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" protocol="dubbo" ref="demoService"/>-->
+    <!--<dubbo:service id="sa" interface="com.alibaba.dubbo.demo.DemoService" protocol="dubbo" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl">-->
+        <!--&lt;!&ndash;<dubbo:method name="sayHello" retries="100">&ndash;&gt;-->
+            <!--&lt;!&ndash;&lt;!&ndash;<dubbo:argument index="0" callback="true" />&ndash;&gt;&ndash;&gt;-->
+            <!--&lt;!&ndash;<dubbo:argument type="com.demo.CallbackListener" callback="true" />&ndash;&gt;-->
+        <!--&lt;!&ndash;</dubbo:method>&ndash;&gt;-->
+        <!--<property name="demoDAO" ref="demoDAO" />-->
+    <!--</dubbo:service>-->
+
+    <!--<dubbo:service id="sb" interface="com.alibaba.dubbo.demo.DemoService" ref="demoService">-->
+        <!--&lt;!&ndash;<dubbo:method name="sayHello" retries="100">&ndash;&gt;-->
+        <!--&lt;!&ndash;&lt;!&ndash;<dubbo:argument index="0" callback="true" />&ndash;&gt;&ndash;&gt;-->
+        <!--&lt;!&ndash;<dubbo:argument type="com.demo.CallbackListener" callback="true" />&ndash;&gt;-->
+        <!--&lt;!&ndash;</dubbo:method>&ndash;&gt;-->
+
+        <dubbo:parameter key="threadname" value="shuaiqi" />
+        <dubbo:parameter key="threads" value="123" />
+        <dubbo:parameter key="queues" value="10" />
+
+        <dubbo:method name="callbackParam">
+            <dubbo:argument callback="true" type="com.alibaba.dubbo.demo.ParamCallback" />
+        </dubbo:method>
+
+    </dubbo:service>
+
+    <!-- use dubbo protocol to export service on port 20880 -->
+    <dubbo:protocol name="dubbo" port="20880" server="netty4" />
+    <!--<dubbo:protocol id="pb" name="dubbo" port="20881"/>-->
 
 </beans>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/resources/dubbo.properties b/dubbo-demo/dubbo-demo-provider/src/main/resources/dubbo.properties
index ad602baa94..c5aef4e316 100644
--- a/dubbo-demo/dubbo-demo-provider/src/main/resources/dubbo.properties
+++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/dubbo.properties
@@ -1 +1,9 @@
 dubbo.application.qos.port=22222
+
+dubbo.registry.address=192.168.0.1
+
+# serviceA
+#dubbo.service.sa.version=1.2.3
+#dubbo.service.sa.protocols=pa,pb
+# serviceB
+#dubbo.service.sb.version=1.2.4
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-http-demo-consumer/pom.xml b/dubbo-demo/dubbo-http-demo-consumer/pom.xml
new file mode 100644
index 0000000000..f763e83cae
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-consumer/pom.xml
@@ -0,0 +1,83 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.alibaba</groupId>
+        <artifactId>dubbo-demo</artifactId>
+        <version>2.6.1</version>
+    </parent>
+    <artifactId>dubbo-http-demo-consumer</artifactId>
+    <packaging>jar</packaging>
+    <name>${project.artifactId}</name>
+    <description>The demo provider module of dubbo project</description>
+    <properties>
+        <skip_maven_deploy>true</skip_maven_deploy>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-demo-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-config-spring</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-registry-zookeeper</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-registry-multicast</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-cluster</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-rpc-http</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>1.5.10.RELEASE</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.25</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.7.25</version>
+        </dependency>
+
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-http-demo-consumer/src/main/java/com/alibaba/dubbo/demo/provider/HttpConsumer.java b/dubbo-demo/dubbo-http-demo-consumer/src/main/java/com/alibaba/dubbo/demo/provider/HttpConsumer.java
new file mode 100644
index 0000000000..024383fff6
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-consumer/src/main/java/com/alibaba/dubbo/demo/provider/HttpConsumer.java
@@ -0,0 +1,30 @@
+package com.alibaba.dubbo.demo.provider;
+
+import com.alibaba.dubbo.demo.HttpDemoService;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class HttpConsumer {
+
+    public static void main(String[] args) {
+        System.setProperty("java.net.preferIPv4Stack", "true");
+        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
+        context.start();
+        HttpDemoService demoService = (HttpDemoService) context.getBean("demoService"); // get remote service proxy
+
+        while (true) {
+            try {
+                Thread.sleep(1000);
+
+                String hello = demoService.hello("world"); // call remote method
+                System.out.println(hello); // get result
+
+
+            } catch (Throwable throwable) {
+                throwable.printStackTrace();
+            }
+
+
+        }
+    }
+
+}
diff --git a/dubbo-demo/dubbo-http-demo-consumer/src/main/java/com/alibaba/dubbo/demo/provider/Main.java b/dubbo-demo/dubbo-http-demo-consumer/src/main/java/com/alibaba/dubbo/demo/provider/Main.java
new file mode 100644
index 0000000000..da78696a2a
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-consumer/src/main/java/com/alibaba/dubbo/demo/provider/Main.java
@@ -0,0 +1,29 @@
+package com.alibaba.dubbo.demo.provider;
+
+import com.alibaba.dubbo.demo.HttpDemoService;
+import org.springframework.boot.SpringApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean;
+
+@Configuration
+public class Main {
+
+//    http://www.baeldung.com/spring-remoting-http-invoker
+
+    @Bean
+    public HttpInvokerProxyFactoryBean invoker() {
+        HttpInvokerProxyFactoryBean invoker = new HttpInvokerProxyFactoryBean();
+        invoker.setServiceUrl("http://192.168.3.17:8080/com.alibaba.dubbo.demo.HttpDemoService");
+        invoker.setServiceInterface(HttpDemoService.class);
+        return invoker;
+    }
+
+    public static void main(String[] args) {
+        HttpDemoService service = SpringApplication
+                .run(Main.class, args)
+                .getBean(HttpDemoService.class);
+        System.out.println("666:" + service.hello("123"));
+    }
+
+}
diff --git a/dubbo-demo/dubbo-http-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml b/dubbo-demo/dubbo-http-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
new file mode 100644
index 0000000000..1fb64a8344
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
+       xmlns="http://www.springframework.org/schema/beans"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
+
+    <!-- consumer's application name, used for tracing dependency relationship (not a matching criterion),
+    don't set it same as provider -->
+    <dubbo:application name="demo-consumer" />
+
+    <!-- use multicast registry center to discover service -->
+    <!--<dubbo:registry address="multicast://224.5.6.7:1234"/>-->
+    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
+
+    <!-- generate proxy for the remote service, then demoService can be used in the same way as the
+    local regular interface -->
+    <dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.HttpDemoService" >
+    </dubbo:reference>
+
+</beans>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-http-demo-consumer/src/main/resources/dubbo.properties b/dubbo-demo/dubbo-http-demo-consumer/src/main/resources/dubbo.properties
new file mode 100644
index 0000000000..c5aef4e316
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-consumer/src/main/resources/dubbo.properties
@@ -0,0 +1,9 @@
+dubbo.application.qos.port=22222
+
+dubbo.registry.address=192.168.0.1
+
+# serviceA
+#dubbo.service.sa.version=1.2.3
+#dubbo.service.sa.protocols=pa,pb
+# serviceB
+#dubbo.service.sb.version=1.2.4
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-http-demo-consumer/src/main/resources/log4j.properties b/dubbo-demo/dubbo-http-demo-consumer/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..d95684642d
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-consumer/src/main/resources/log4j.properties
@@ -0,0 +1,7 @@
+###set log levels###
+log4j.rootLogger=info, stdout
+###output to the console###
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-http-demo-provider/pom.xml b/dubbo-demo/dubbo-http-demo-provider/pom.xml
new file mode 100644
index 0000000000..e05947bd6e
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-provider/pom.xml
@@ -0,0 +1,64 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.alibaba</groupId>
+        <artifactId>dubbo-demo</artifactId>
+        <version>2.6.1</version>
+    </parent>
+    <artifactId>dubbo-http-demo-provider</artifactId>
+    <packaging>jar</packaging>
+    <name>${project.artifactId}</name>
+    <description>The demo provider module of dubbo project</description>
+    <properties>
+        <skip_maven_deploy>true</skip_maven_deploy>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-demo-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-config-spring</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-registry-zookeeper</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-registry-multicast</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-cluster</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-rpc-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-remoting-http</artifactId>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-http-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-http-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java
new file mode 100644
index 0000000000..ad73536e7b
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.demo.provider;
+
+import com.alibaba.dubbo.demo.HttpDemoService;
+
+public class DemoServiceImpl implements HttpDemoService {
+
+
+    @Override
+    public String hello(String msg) {
+        return "response:" + msg;
+    }
+}
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-http-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/HttpProvider.java b/dubbo-demo/dubbo-http-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/HttpProvider.java
new file mode 100644
index 0000000000..bcfea0e002
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/HttpProvider.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.demo.provider;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class HttpProvider {
+
+    public static void main(String[] args) throws Exception {
+        //Prevent to get IPV6 address,this way only work in debug mode
+        //But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
+        System.setProperty("java.net.preferIPv4Stack", "true");
+        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
+        context.start();
+
+        System.in.read(); // press any key to exit
+    }
+
+}
diff --git a/dubbo-demo/dubbo-http-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml b/dubbo-demo/dubbo-http-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
new file mode 100644
index 0000000000..fb8a97857c
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
+       xmlns="http://www.springframework.org/schema/beans"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
+
+    <!-- provider's application name, used for tracing dependency relationship -->
+    <dubbo:application name="demo-provider"/>
+
+    <dubbo:provider delay="-1" retries="0" />
+
+    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
+
+    <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
+
+    <!-- declare the service interface to be exported -->
+    <dubbo:service interface="com.alibaba.dubbo.demo.HttpDemoService" ref="demoService">
+    </dubbo:service>
+
+    <!-- use dubbo protocol to export service on port 20880 -->
+    <dubbo:protocol name="http" port="8080" server="tomcat" />
+    <!--<dubbo:protocol id="pb" name="dubbo" port="20881"/>-->
+
+</beans>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-http-demo-provider/src/main/resources/dubbo.properties b/dubbo-demo/dubbo-http-demo-provider/src/main/resources/dubbo.properties
new file mode 100644
index 0000000000..c5aef4e316
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-provider/src/main/resources/dubbo.properties
@@ -0,0 +1,9 @@
+dubbo.application.qos.port=22222
+
+dubbo.registry.address=192.168.0.1
+
+# serviceA
+#dubbo.service.sa.version=1.2.3
+#dubbo.service.sa.protocols=pa,pb
+# serviceB
+#dubbo.service.sb.version=1.2.4
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-http-demo-provider/src/main/resources/log4j.properties b/dubbo-demo/dubbo-http-demo-provider/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..d95684642d
--- /dev/null
+++ b/dubbo-demo/dubbo-http-demo-provider/src/main/resources/log4j.properties
@@ -0,0 +1,7 @@
+###set log levels###
+log4j.rootLogger=info, stdout
+###output to the console###
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-rest-demo-provider/pom.xml b/dubbo-demo/dubbo-rest-demo-provider/pom.xml
new file mode 100644
index 0000000000..caa5d8e939
--- /dev/null
+++ b/dubbo-demo/dubbo-rest-demo-provider/pom.xml
@@ -0,0 +1,60 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.alibaba</groupId>
+        <artifactId>dubbo-demo</artifactId>
+        <version>2.6.1</version>
+    </parent>
+    <artifactId>dubbo-rest-demo-provider</artifactId>
+    <packaging>jar</packaging>
+    <name>${project.artifactId}</name>
+    <description>The demo provider module of dubbo project</description>
+    <properties>
+        <skip_maven_deploy>true</skip_maven_deploy>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-demo-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-config-spring</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-registry-zookeeper</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-registry-multicast</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-cluster</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>dubbo-rpc-rest</artifactId>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-rest-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-rest-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java
new file mode 100644
index 0000000000..0cc5372d1b
--- /dev/null
+++ b/dubbo-demo/dubbo-rest-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.demo.provider;
+
+import com.alibaba.dubbo.demo.HttpDemoService;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+
+@Path("demo")
+public class DemoServiceImpl implements HttpDemoService {
+
+    @GET
+    @Path("hello")
+    @Override
+    public String hello(@QueryParam("msg") String msg) {
+        return "response:" + msg;
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-rest-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/RestProvider.java b/dubbo-demo/dubbo-rest-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/RestProvider.java
new file mode 100644
index 0000000000..65fcd03dcf
--- /dev/null
+++ b/dubbo-demo/dubbo-rest-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/RestProvider.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.demo.provider;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class RestProvider {
+
+    public static void main(String[] args) throws Exception {
+        //Prevent to get IPV6 address,this way only work in debug mode
+        //But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
+        System.setProperty("java.net.preferIPv4Stack", "true");
+        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
+        context.start();
+
+        System.in.read(); // press any key to exit
+    }
+
+}
diff --git a/dubbo-demo/dubbo-rest-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml b/dubbo-demo/dubbo-rest-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
new file mode 100644
index 0000000000..bd77ce197a
--- /dev/null
+++ b/dubbo-demo/dubbo-rest-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
+       xmlns="http://www.springframework.org/schema/beans"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
+
+    <!-- provider's application name, used for tracing dependency relationship -->
+    <dubbo:application name="demo-provider"/>
+
+    <dubbo:provider delay="-1" retries="0" />
+
+    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
+
+    <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
+
+    <!-- declare the service interface to be exported -->
+    <dubbo:service interface="com.alibaba.dubbo.demo.HttpDemoService" ref="demoService">
+    </dubbo:service>
+
+    <!-- use dubbo protocol to export service on port 20880 -->
+    <dubbo:protocol name="rest" port="8080" server="tomcat" />
+    <!--<dubbo:protocol id="pb" name="dubbo" port="20881"/>-->
+
+</beans>
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-rest-demo-provider/src/main/resources/dubbo.properties b/dubbo-demo/dubbo-rest-demo-provider/src/main/resources/dubbo.properties
new file mode 100644
index 0000000000..c5aef4e316
--- /dev/null
+++ b/dubbo-demo/dubbo-rest-demo-provider/src/main/resources/dubbo.properties
@@ -0,0 +1,9 @@
+dubbo.application.qos.port=22222
+
+dubbo.registry.address=192.168.0.1
+
+# serviceA
+#dubbo.service.sa.version=1.2.3
+#dubbo.service.sa.protocols=pa,pb
+# serviceB
+#dubbo.service.sb.version=1.2.4
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-rest-demo-provider/src/main/resources/log4j.properties b/dubbo-demo/dubbo-rest-demo-provider/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..d95684642d
--- /dev/null
+++ b/dubbo-demo/dubbo-rest-demo-provider/src/main/resources/log4j.properties
@@ -0,0 +1,7 @@
+###set log levels###
+log4j.rootLogger=info, stdout
+###output to the console###
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n
\ No newline at end of file
diff --git a/dubbo-demo/pom.xml b/dubbo-demo/pom.xml
index f904840214..5a0fe408c3 100644
--- a/dubbo-demo/pom.xml
+++ b/dubbo-demo/pom.xml
@@ -33,6 +33,10 @@ limitations under the License.
         <module>dubbo-demo-api</module>
         <module>dubbo-demo-provider</module>
         <module>dubbo-demo-consumer</module>
+        <module>dubbo-demo-injvm</module>
+        <module>dubbo-http-demo-provider</module>
+        <module>dubbo-http-demo-consumer</module>
+        <module>dubbo-rest-demo-provider</module>
     </modules>
 
     <dependencyManagement>
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/NotifyListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/NotifyListener.java
index 964aab0630..3fe097a9d3 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/NotifyListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/NotifyListener.java
@@ -23,6 +23,8 @@
 /**
  * NotifyListener. (API, Prototype, ThreadSafe)
  *
+ * 通知监听器
+ *
  * @see com.alibaba.dubbo.registry.RegistryService#subscribe(URL, NotifyListener)
  */
 public interface NotifyListener {
@@ -39,6 +41,18 @@
      *
      * @param urls The list of registered information , is always not empty. The meaning is the same as the return value of {@link com.alibaba.dubbo.registry.RegistryService#lookup(URL)}.
      */
+    /**
+     * 当收到服务变更通知时触发。
+     * <p>
+     * 通知需处理契约:<br>
+     * 1. 总是以服务接口和数据类型为维度全量通知,即不会通知一个服务的同类型的部分数据,用户不需要对比上一次通知结果。<br>
+     * 2. 订阅时的第一次通知,必须是一个服务的所有类型数据的全量通知。<br>
+     * 3. 中途变更时,允许不同类型的数据分开通知,比如:providers, consumers, routers, overrides,允许只通知其中一种类型,但该类型的数据必须是全量的,不是增量的。<br>
+     * 4. 如果一种类型的数据为空,需通知一个empty协议并带category参数的标识性URL数据。<br>
+     * 5. 通知者(即注册中心实现)需保证通知的顺序,比如:单线程推送,队列串行化,带版本对比。<br>
+     *
+     * @param urls 已注册信息列表,总不为空,含义同{@link com.alibaba.dubbo.registry.RegistryService#lookup(URL)}的返回值。
+     */
     void notify(List<URL> urls);
 
 }
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/Registry.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/Registry.java
index 94b519df0d..9660aa1d8b 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/Registry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/Registry.java
@@ -22,6 +22,8 @@
 /**
  * Registry. (SPI, Prototype, ThreadSafe)
  *
+ * 注册中心接口
+ *
  * @see com.alibaba.dubbo.registry.RegistryFactory#getRegistry(URL)
  * @see com.alibaba.dubbo.registry.support.AbstractRegistry
  */
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/RegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/RegistryFactory.java
index b7eca34b19..ed999da7af 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/RegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/RegistryFactory.java
@@ -23,6 +23,8 @@
 /**
  * RegistryFactory. (SPI, Singleton, ThreadSafe)
  *
+ * 注册中心工厂
+ *
  * @see com.alibaba.dubbo.registry.support.AbstractRegistryFactory
  */
 @SPI("dubbo")
@@ -42,6 +44,20 @@
      * @param url Registry address, is not allowed to be empty
      * @return Registry reference, never return empty value
      */
+    /**
+     * 连接注册中心.
+     * <p>
+     * 连接注册中心需处理契约:<br>
+     * 1. 当设置check=false时表示不检查连接,否则在连接不上时抛出异常。<br>
+     * 2. 支持URL上的username:password权限认证。<br>
+     * 3. 支持backup=10.20.153.10备选注册中心集群地址。<br>
+     * 4. 支持file=registry.cache本地磁盘文件缓存。<br>
+     * 5. 支持timeout=1000请求超时设置。<br>
+     * 6. 支持session=60000会话超时或过期设置。<br>
+     *
+     * @param url 注册中心地址,不允许为空
+     * @return 注册中心引用,总不返回空
+     */
     @Adaptive({"protocol"})
     Registry getRegistry(URL url);
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/RegistryService.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/RegistryService.java
index 764c5d5427..62e96402f1 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/RegistryService.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/RegistryService.java
@@ -23,6 +23,8 @@
 /**
  * RegistryService. (SPI, Prototype, ThreadSafe)
  *
+ * 注册中心服务接口
+ *
  * @see com.alibaba.dubbo.registry.Registry
  * @see com.alibaba.dubbo.registry.RegistryFactory#getRegistry(URL)
  */
@@ -40,6 +42,18 @@
      *
      * @param url  Registration information , is not allowed to be empty, e.g: dubbo://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
      */
+    /**
+     * 注册数据,比如:提供者地址,消费者地址,路由规则,覆盖规则,等数据。
+     * <p>
+     * 注册需处理契约:<br>
+     * 1. 当URL设置了check=false时,注册失败后不报错,在后台定时重试,否则抛出异常。<br>
+     * 2. 当URL设置了dynamic=false参数,则需持久存储,否则,当注册者出现断电等情况异常退出时,需自动删除。<br>
+     * 3. 当URL设置了category=routers时,表示分类存储,缺省类别为providers,可按分类部分通知数据。<br>
+     * 4. 当注册中心重启,网络抖动,不能丢失数据,包括断线自动删除数据。<br>
+     * 5. 允许URI相同但参数不同的URL并存,不能覆盖。<br>
+     *
+     * @param url 注册信息,不允许为空,如:dubbo://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
+     */
     void register(URL url);
 
     /**
@@ -51,6 +65,15 @@
      *
      * @param url Registration information , is not allowed to be empty, e.g: dubbo://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
      */
+    /**
+     * 取消注册.
+     * <p>
+     * 取消注册需处理契约:<br>
+     * 1. 如果是dynamic=false的持久存储数据,找不到注册数据,则抛IllegalStateException,否则忽略。<br>
+     * 2. 按全URL匹配取消注册。<br>
+     *
+     * @param url 注册信息,不允许为空,如:dubbo://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
+     */
     void unregister(URL url);
 
     /**
@@ -68,6 +91,21 @@
      * @param url      Subscription condition, not allowed to be empty, e.g. consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
      * @param listener A listener of the change event, not allowed to be empty
      */
+    /**
+     * 订阅符合条件的已注册数据,当有注册数据变更时自动推送.
+     * <p>
+     * 订阅需处理契约:<br>
+     * 1. 当URL设置了check=false时,订阅失败后不报错,在后台定时重试。<br>
+     * 2. 当URL设置了category=routers,只通知指定分类的数据,多个分类用逗号分隔,并允许星号通配,表示订阅所有分类数据。<br>
+     * 3. 允许以interface,group,version,classifier作为条件查询,如:interface=com.alibaba.foo.BarService&version=1.0.0<br>
+     * 4. 并且查询条件允许星号通配,订阅所有接口的所有分组的所有版本,或:interface=*&group=*&version=*&classifier=*<br>
+     * 5. 当注册中心重启,网络抖动,需自动恢复订阅请求。<br>
+     * 6. 允许URI相同但参数不同的URL并存,不能覆盖。<br>
+     * 7. 必须阻塞订阅过程,等第一次通知完后再返回。<br>
+     *
+     * @param url      订阅条件,不允许为空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
+     * @param listener 变更事件监听器,不允许为空
+     */
     void subscribe(URL url, NotifyListener listener);
 
     /**
@@ -80,6 +118,16 @@
      * @param url      Subscription condition, not allowed to be empty, e.g. consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
      * @param listener A listener of the change event, not allowed to be empty
      */
+    /**
+     * 取消订阅.
+     * <p>
+     * 取消订阅需处理契约:<br>
+     * 1. 如果没有订阅,直接忽略。<br>
+     * 2. 按全URL匹配取消订阅。<br>
+     *
+     * @param url      订阅条件,不允许为空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
+     * @param listener 变更事件监听器,不允许为空
+     */
     void unsubscribe(URL url, NotifyListener listener);
 
     /**
@@ -89,6 +137,13 @@
      * @return The registered information list, which may be empty, the meaning is the same as the parameters of {@link com.alibaba.dubbo.registry.NotifyListener#notify(List<URL>)}.
      * @see com.alibaba.dubbo.registry.NotifyListener#notify(List)
      */
+    /**
+     * 查询符合条件的已注册数据,与订阅的推模式相对应,这里为拉模式,只返回一次结果。
+     *
+     * @param url 查询条件,不允许为空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
+     * @return 已注册信息列表,可能为空,含义同{@link com.alibaba.dubbo.registry.NotifyListener#notify(List<URL>)}的参数。
+     * @see com.alibaba.dubbo.registry.NotifyListener#notify(List)
+     */
     List<URL> lookup(URL url);
 
 }
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryProtocol.java
index 14a516137f..4dea318adb 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryProtocol.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryProtocol.java
@@ -54,17 +54,38 @@
 /**
  * RegistryProtocol
  *
+ * 注册中心协议实现类。
  */
 public class RegistryProtocol implements Protocol {
 
     private final static Logger logger = LoggerFactory.getLogger(RegistryProtocol.class);
+
+    /**
+     * 单例。在 Dubbo SPI 中,被初始化,有且仅有一次。
+     */
     private static RegistryProtocol INSTANCE;
     private final Map<URL, NotifyListener> overrideListeners = new ConcurrentHashMap<URL, NotifyListener>();
-    //To solve the problem of RMI repeated exposure port conflicts, the services that have been exposed are no longer exposed.
-    //providerurl <--> exporter
+
+    /**
+     * 绑定关系集合。
+     *
+     * key:服务 Dubbo URL
+     */
+    // To solve the problem of RMI repeated exposure port conflicts, the services that have been exposed are no longer exposed.
+    // 用于解决rmi重复暴露端口冲突的问题,已经暴露过的服务不再重新暴露
+    // providerurl <--> exporter
     private final Map<String, ExporterChangeableWrapper<?>> bounds = new ConcurrentHashMap<String, ExporterChangeableWrapper<?>>();
+    /**
+     * Cluster 自适应拓展实现类对象
+     */
     private Cluster cluster;
+    /**
+     * Protocol 自适应拓展实现类,通过 Dubbo SPI 自动注入。
+     */
     private Protocol protocol;
+    /**
+     * RegistryFactory 自适应拓展实现类,通过 Dubbo SPI 自动注入。
+     */
     private RegistryFactory registryFactory;
     private ProxyFactory proxyFactory;
 
@@ -79,7 +100,7 @@ public static RegistryProtocol getRegistryProtocol() {
         return INSTANCE;
     }
 
-    //Filter the parameters that do not need to be output in url(Starting with .)
+    // Filter the parameters that do not need to be output in url(Starting with .)
     private static String[] getFilteredKeys(URL url) {
         Map<String, String> params = url.getParameters();
         if (params != null && !params.isEmpty()) {
@@ -125,25 +146,33 @@ public void register(URL registryUrl, URL registedProviderUrl) {
     }
 
     public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
-        //export invoker
+        // 暴露服务
+        // export invoker
         final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);
 
+        // 获得注册中心 URL
         URL registryUrl = getRegistryUrl(originInvoker);
 
-        //registry provider
+        // 获得注册中心对象
+        // registry provider
         final Registry registry = getRegistry(originInvoker);
+
+        // 获得服务提供者 URL
         final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);
 
         //to judge to delay publish whether or not
         boolean register = registedProviderUrl.getParameter("register", true);
 
+        // 向注册中心订阅服务消费者
         ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registedProviderUrl);
 
+        // 向注册中心注册服务提供者(自己)
         if (register) {
             register(registryUrl, registedProviderUrl);
-            ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true);
+            ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true); // // 标记向本地注册表的注册服务提供者,已经注册
         }
 
+        // 【TODO 8015】配置规则
         // Subscribe the override data
         // FIXME When the provider subscribes, it will affect the scene : a certain JVM exposes the service and call the same service. Because the subscribed is cached key with the name of the service, it causes the subscription information to cover.
         final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registedProviderUrl);
@@ -154,16 +183,32 @@ public void register(URL registryUrl, URL registedProviderUrl) {
         return new DestroyableExporter<T>(exporter, originInvoker, overrideSubscribeUrl, registedProviderUrl);
     }
 
+    /**
+     * 暴露服务。
+     *
+     * 此处的 Local 指的是,本地启动服务,但是不包括向注册中心注册服务的意思。
+     *
+     * @param originInvoker 原始 Invoker
+     * @param <T> 泛型
+     * @return Exporter 对象
+     */
     @SuppressWarnings("unchecked")
     private <T> ExporterChangeableWrapper<T> doLocalExport(final Invoker<T> originInvoker) {
+        // 获得在 `bounds` 中的缓存 Key
         String key = getCacheKey(originInvoker);
+        // 从 `bounds` 获得,是不是已经暴露过服务
         ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
         if (exporter == null) {
             synchronized (bounds) {
                 exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
+                // 未暴露过,进行暴露服务
                 if (exporter == null) {
+                    // 创建 Invoker Delegate 对象
                     final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));
+                    // 暴露服务,创建 Exporter 对象
+                    // 使用 创建的Exporter对象 + originInvoker ,创建 ExporterChangeableWrapper 对象
                     exporter = new ExporterChangeableWrapper<T>((Exporter<T>) protocol.export(invokerDelegete), originInvoker);
+                    // 添加到 `bounds`
                     bounds.put(key, exporter);
                 }
             }
@@ -200,9 +245,15 @@ private Registry getRegistry(final Invoker<?> originInvoker) {
         return registryFactory.getRegistry(registryUrl);
     }
 
+    /**
+     * 获得注册中心 URL
+     *
+     * @param originInvoker 原始 Invoker
+     * @return URL
+     */
     private URL getRegistryUrl(Invoker<?> originInvoker) {
         URL registryUrl = originInvoker.getUrl();
-        if (Constants.REGISTRY_PROTOCOL.equals(registryUrl.getProtocol())) {
+        if (Constants.REGISTRY_PROTOCOL.equals(registryUrl.getProtocol())) { // protocol
             String protocol = registryUrl.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_DIRECTORY);
             registryUrl = registryUrl.setProtocol(protocol).removeParameter(Constants.REGISTRY_KEY);
         }
@@ -217,16 +268,16 @@ private URL getRegistryUrl(Invoker<?> originInvoker) {
      * @return
      */
     private URL getRegistedProviderUrl(final Invoker<?> originInvoker) {
+        // 从注册中心的 export 参数中,获得服务提供者的 URL
         URL providerUrl = getProviderUrl(originInvoker);
         //The address you see at the registry
-        final URL registedProviderUrl = providerUrl.removeParameters(getFilteredKeys(providerUrl))
-                .removeParameter(Constants.MONITOR_KEY)
-                .removeParameter(Constants.BIND_IP_KEY)
-                .removeParameter(Constants.BIND_PORT_KEY)
-                .removeParameter(QOS_ENABLE)
-                .removeParameter(QOS_PORT)
-                .removeParameter(ACCEPT_FOREIGN_IP);
-        return registedProviderUrl;
+        return providerUrl.removeParameters(getFilteredKeys(providerUrl)) // 移除 .hide 为前缀的参数
+                .removeParameter(Constants.MONITOR_KEY) // monitor
+                .removeParameter(Constants.BIND_IP_KEY) // bind.ip
+                .removeParameter(Constants.BIND_PORT_KEY) // bind.port
+                .removeParameter(QOS_ENABLE) // qos.enable
+                .removeParameter(QOS_PORT) // qos.port
+                .removeParameter(ACCEPT_FOREIGN_IP); // qos.accept.foreign.ip
     }
 
     private URL getSubscribedOverrideUrl(URL registedProviderUrl) {
@@ -238,48 +289,56 @@ private URL getSubscribedOverrideUrl(URL registedProviderUrl) {
     /**
      * Get the address of the providerUrl through the url of the invoker
      *
+     * 通过 invoker 的 url 获取 providerUrl 的地址
+     *
      * @param origininvoker
      * @return
      */
     private URL getProviderUrl(final Invoker<?> origininvoker) {
-        String export = origininvoker.getUrl().getParameterAndDecoded(Constants.EXPORT_KEY);
+        String export = origininvoker.getUrl().getParameterAndDecoded(Constants.EXPORT_KEY); // export
         if (export == null || export.length() == 0) {
             throw new IllegalArgumentException("The registry export url is null! registry: " + origininvoker.getUrl());
         }
-
-        URL providerUrl = URL.valueOf(export);
-        return providerUrl;
+        return URL.valueOf(export);
     }
 
     /**
      * Get the key cached in bounds by invoker
      *
-     * @param originInvoker
-     * @return
+     * 获 取invoker 在 bounds中 缓存的key
+     *
+     * @param originInvoker 原始 Invoker
+     * @return url 字符串
      */
     private String getCacheKey(final Invoker<?> originInvoker) {
         URL providerUrl = getProviderUrl(originInvoker);
-        String key = providerUrl.removeParameters("dynamic", "enabled").toFullString();
-        return key;
+        return providerUrl.removeParameters("dynamic", "enabled").toFullString();
     }
 
     @SuppressWarnings("unchecked")
     public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
+        // 获得真实的注册中心的 URL
         url = url.setProtocol(url.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_REGISTRY)).removeParameter(Constants.REGISTRY_KEY);
+        // 获得注册中心
         Registry registry = registryFactory.getRegistry(url);
+        // TODO 芋艿
         if (RegistryService.class.equals(type)) {
             return proxyFactory.getInvoker((T) registry, type, url);
         }
 
+        // 获得服务引用配置参数集合
         // group="a,b" or group="*"
         Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded(Constants.REFER_KEY));
         String group = qs.get(Constants.GROUP_KEY);
+        // 分组聚合,参见文档 http://dubbo.io/books/dubbo-user-book/demos/group-merger.html
         if (group != null && group.length() > 0) {
             if ((Constants.COMMA_SPLIT_PATTERN.split(group)).length > 1
                     || "*".equals(group)) {
+                // 执行服务引用
                 return doRefer(getMergeableCluster(), registry, type, url);
             }
         }
+        // 执行服务引用
         return doRefer(cluster, registry, type, url);
     }
 
@@ -287,25 +346,41 @@ private Cluster getMergeableCluster() {
         return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension("mergeable");
     }
 
+    /**
+     * 执行服务引用,返回 Invoker 对象
+     *
+     * @param cluster Cluster 对象
+     * @param registry 注册中心对象
+     * @param type 服务接口类型
+     * @param url 注册中心 URL
+     * @param <T> 泛型
+     * @return Invoker 对象
+     */
     private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
+        // 创建 RegistryDirectory 对象,并设置注册中心
         RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
         directory.setRegistry(registry);
         directory.setProtocol(protocol);
+        // 创建订阅 URL
         // all attributes of REFER_KEY
-        Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters());
+        Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters()); // 服务引用配置集合
         URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, parameters.remove(Constants.REGISTER_IP_KEY), 0, type.getName(), parameters);
+        // 向注册中心注册自己(服务消费者)
         if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
                 && url.getParameter(Constants.REGISTER_KEY, true)) {
             registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
                     Constants.CHECK_KEY, String.valueOf(false)));
         }
+        // 向注册中心订阅服务提供者
         directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY,
                 Constants.PROVIDERS_CATEGORY
                         + "," + Constants.CONFIGURATORS_CATEGORY
                         + "," + Constants.ROUTERS_CATEGORY));
 
+        // 创建 Invoker 对象,【TODO 8015】集群容错
         Invoker invoker = cluster.join(directory);
-        ProviderConsumerRegTable.registerConsuemr(invoker, url, subscribeUrl, directory);
+        // 向本地注册表,注册消费者
+        ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
         return invoker;
     }
 
@@ -318,6 +393,12 @@ public void destroy() {
     }
 
     public static class InvokerDelegete<T> extends InvokerWrapper<T> {
+
+        /**
+         * Invoker 对象
+         *
+         * 因为父类未提供 invoker 属性的获取方法,因此这里增加了和父类 invoker 一样的这个属性。
+         */
         private final Invoker<T> invoker;
 
         /**
@@ -422,11 +503,19 @@ private URL getConfigedInvokerUrl(List<Configurator> configurators, URL url) {
     /**
      * exporter proxy, establish the corresponding relationship between the returned exporter and the exporter exported by the protocol, and can modify the relationship at the time of override.
      *
+     * exporter 代理, 建立返回的 exporter 与 protocol export 出的 exporter 的对应关系,在 override 时可以进行关系修改.
+     *
      * @param <T>
      */
     private class ExporterChangeableWrapper<T> implements Exporter<T> {
 
+        /**
+         * 原 Invoker 对象
+         */
         private final Invoker<T> originInvoker;
+        /**
+         * 暴露的 Exporter 对象
+         */
         private Exporter<T> exporter;
 
         public ExporterChangeableWrapper(Exporter<T> exporter, Invoker<T> originInvoker) {
@@ -448,11 +537,18 @@ public void setExporter(Exporter<T> exporter) {
 
         public void unexport() {
             String key = getCacheKey(this.originInvoker);
+            // 移除出 `bounds`
             bounds.remove(key);
+            // 取消暴露
             exporter.unexport();
         }
     }
 
+    /**
+     * 可销毁的 Exporter
+     *
+     * @param <T> 泛型
+     */
     static private class DestroyableExporter<T> implements Exporter<T> {
 
         public static final ExecutorService executor = Executors.newSingleThreadExecutor(new NamedThreadFactory("Exporter-Unexport", true));
@@ -474,12 +570,15 @@ public DestroyableExporter(Exporter<T> exporter, Invoker<T> originInvoker, URL s
         }
 
         public void unexport() {
+            //
             Registry registry = RegistryProtocol.INSTANCE.getRegistry(originInvoker);
             try {
                 registry.unregister(registerUrl);
             } catch (Throwable t) {
                 logger.warn(t.getMessage(), t);
             }
+
+            //
             try {
                 NotifyListener listener = RegistryProtocol.INSTANCE.overrideListeners.remove(subscribeUrl);
                 registry.unsubscribe(subscribeUrl, listener);
@@ -487,6 +586,7 @@ public void unexport() {
                 logger.warn(t.getMessage(), t);
             }
 
+            //
             executor.submit(new Runnable() {
                 @Override
                 public void run() {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/AbstractRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/AbstractRegistry.java
index 55e2455c84..6f55b3d932 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/AbstractRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/AbstractRegistry.java
@@ -53,35 +53,87 @@
 /**
  * AbstractRegistry. (SPI, Prototype, ThreadSafe)
  *
+ * Registry 抽象类,实现了如下方法:
+ *
+ * 1、通用的注册、订阅、查询、通知等方法
+ * 2、读取和持久化注册数据到文件,以 properties 格式存储
  */
 public abstract class AbstractRegistry implements Registry {
 
+    // URL地址分隔符,用于文件缓存中,服务提供者URL分隔
     // URL address separator, used in file cache, service provider URL separation
     private static final char URL_SEPARATOR = ' ';
+    // URL地址分隔正则表达式,用于解析文件缓存中服务提供者URL列表
     // URL address separated regular expression for parsing the service provider URL list in the file cache
     private static final String URL_SPLIT = "\\s+";
+
     // Log output
     protected final Logger logger = LoggerFactory.getLogger(getClass());
+    /**
+     *  本地磁盘缓存。
+     *
+     *  1. 其中特殊的 key 值 .registies 记录注册中心列表 TODO 8019 芋艿,特殊的 key 是
+     *  2. 其它均为 {@link #notified} 服务提供者列表
+     */
     // Local disk cache, where the special key value.registies records the list of registry centers, and the others are the list of notified service providers
     private final Properties properties = new Properties();
+    /**
+     * 注册中心缓存写入执行器。
+     *
+     * 线程数=1
+     */
     // File cache timing writing
     private final ExecutorService registryCacheExecutor = Executors.newFixedThreadPool(1, new NamedThreadFactory("DubboSaveRegistryCache", true));
+    /**
+     * 是否同步保存文件
+     */
     // Is it synchronized to save the file
     private final boolean syncSaveFile;
+    /**
+     * 数据版本号
+     *
+     * {@link #properties}
+     */
     private final AtomicLong lastCacheChanged = new AtomicLong();
+    /**
+     * 已注册 URL 集合。
+     *
+     * 注意,注册的 URL 不仅仅可以是服务提供者的,也可以是服务消费者的
+     */
     private final Set<URL> registered = new ConcurrentHashSet<URL>();
+    /**
+     * 订阅 URL 的监听器集合
+     *
+     * key:消费者的 URL ,例如消费者的 URL
+     */
     private final ConcurrentMap<URL, Set<NotifyListener>> subscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>();
+    /**
+     * 被通知的 URL 集合
+     *
+     * key1:消费者的 URL ,例如消费者的 URL ,和 {@link #subscribed} 的键一致
+     * key2:分类,例如:providers、consumers、routes、configurators。【实际无 consumers ,因为消费者不会去订阅另外的消费者的列表】
+     *            在 {@link Constants} 中,以 "_CATEGORY" 结尾
+     */
     private final ConcurrentMap<URL, Map<String, List<URL>>> notified = new ConcurrentHashMap<URL, Map<String, List<URL>>>();
+    /**
+     * 注册中心 URL
+     */
     private URL registryUrl;
+    /**
+     * 本地磁盘缓存文件,缓存注册中心的数据
+     */
     // Local disk cache file
     private File file;
-
+    /**
+     * 是否销毁
+     */
     private AtomicBoolean destroyed = new AtomicBoolean(false);
 
     public AbstractRegistry(URL url) {
         setUrl(url);
         // Start file save timer
         syncSaveFile = url.getParameter(Constants.REGISTRY_FILESAVE_SYNC_KEY, false);
+        // 获得 `file`
         String filename = url.getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getParameter(Constants.APPLICATION_KEY) + "-" + url.getAddress() + ".cache");
         File file = null;
         if (ConfigUtils.isNotEmpty(filename)) {
@@ -93,8 +145,10 @@ public AbstractRegistry(URL url) {
             }
         }
         this.file = file;
+        // 加载本地磁盘缓存文件到内存缓存
         loadProperties();
-        notify(url.getBackupUrls());
+        // 通知监听器,URL 变化结果
+        notify(url.getBackupUrls()); // 【TODO 8020】为什么构造方法,要通知,连监听器都没注册
     }
 
     protected static List<URL> filterEmpty(URL url, List<URL> urls) {
@@ -106,6 +160,7 @@ public AbstractRegistry(URL url) {
         return urls;
     }
 
+    @Override
     public URL getUrl() {
         return registryUrl;
     }
@@ -141,6 +196,11 @@ public AtomicLong getLastCacheChanged() {
         return lastCacheChanged;
     }
 
+    /**
+     * 保存内存缓存到本地磁盘缓存文件,即 {@link #properties} => {@link #file}
+     *
+     * @param version 数据版本号
+     */
     public void doSaveProperties(long version) {
         if (version < lastCacheChanged.get()) {
             return;
@@ -150,18 +210,23 @@ public void doSaveProperties(long version) {
         }
         // Save
         try {
+            // 创建 .lock 文件
             File lockfile = new File(file.getAbsolutePath() + ".lock");
             if (!lockfile.exists()) {
                 lockfile.createNewFile();
             }
+            // 随机读写文件操作
             RandomAccessFile raf = new RandomAccessFile(lockfile, "rw");
             try {
                 FileChannel channel = raf.getChannel();
                 try {
+                    // 获得文件锁
                     FileLock lock = channel.tryLock();
+                    // 获取失败
                     if (lock == null) {
                         throw new IOException("Can not lock the registry cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties");
                     }
+                    // 获取成功,进行保存
                     // Save
                     try {
                         if (!file.exists()) {
@@ -173,18 +238,23 @@ public void doSaveProperties(long version) {
                         } finally {
                             outputFile.close();
                         }
+                    // 释放文件锁
                     } finally {
                         lock.release();
                     }
+                // 释放文件 Channel
                 } finally {
                     channel.close();
                 }
+            // 释放随机读写文件操作
             } finally {
                 raf.close();
             }
         } catch (Throwable e) {
+            // 版本号过小,不保存
             if (version < lastCacheChanged.get()) {
                 return;
+            // 重新异步保存,一般情况下为上面的获取锁失败抛出的异常。通过这样的方式,达到保存成功。
             } else {
                 registryCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet()));
             }
@@ -192,11 +262,16 @@ public void doSaveProperties(long version) {
         }
     }
 
+    /**
+     * 加载本地磁盘缓存文件到内存缓存,即 {@link #file} => {@link #properties}
+     */
     private void loadProperties() {
         if (file != null && file.exists()) {
             InputStream in = null;
             try {
+                // 文件流
                 in = new FileInputStream(file);
+                // 读取文件流
                 properties.load(in);
                 if (logger.isInfoEnabled()) {
                     logger.info("Load registry store file " + file + ", data: " + properties);
@@ -215,13 +290,20 @@ private void loadProperties() {
         }
     }
 
+    /**
+     * 从 `properties` 中获得缓存的 URL 集合
+     *
+     * @param url URL
+     * @return URL 集合
+     */
     public List<URL> getCacheUrls(URL url) {
         for (Map.Entry<Object, Object> entry : properties.entrySet()) {
             String key = (String) entry.getKey();
             String value = (String) entry.getValue();
-            if (key != null && key.length() > 0 && key.equals(url.getServiceKey())
-                    && (Character.isLetter(key.charAt(0)) || key.charAt(0) == '_')
-                    && value != null && value.length() > 0) {
+            if (key != null && key.length() > 0 // 非空
+                    && key.equals(url.getServiceKey()) // 服务键匹配
+                    && (Character.isLetter(key.charAt(0)) || key.charAt(0) == '_') // TODO 芋艿,_ 是什么
+                    && value != null && value.length() > 0) { // 值非空
                 String[] arr = value.trim().split(URL_SPLIT);
                 List<URL> urls = new ArrayList<URL>();
                 for (String u : arr) {
@@ -233,10 +315,13 @@ private void loadProperties() {
         return null;
     }
 
+    @Override
     public List<URL> lookup(URL url) {
         List<URL> result = new ArrayList<URL>();
         Map<String, List<URL>> notifiedUrls = getNotified().get(url);
+        // 有数据,遍历数据获得
         if (notifiedUrls != null && notifiedUrls.size() > 0) {
+            // 遍历
             for (List<URL> urls : notifiedUrls.values()) {
                 for (URL u : urls) {
                     if (!Constants.EMPTY_PROTOCOL.equals(u.getProtocol())) {
@@ -244,15 +329,19 @@ private void loadProperties() {
                     }
                 }
             }
+        // 无数据,通过发起订阅的方式得到数据后,遍历数据获得
         } else {
+            // 创建 NotifyListener 对象
             final AtomicReference<List<URL>> reference = new AtomicReference<List<URL>>();
             NotifyListener listener = new NotifyListener() {
                 public void notify(List<URL> urls) {
                     reference.set(urls);
                 }
             };
+            // 订阅获得数据
             subscribe(url, listener); // Subscribe logic guarantees the first notify to return
             List<URL> urls = reference.get();
+            // 遍历
             if (urls != null && !urls.isEmpty()) {
                 for (URL u : urls) {
                     if (!Constants.EMPTY_PROTOCOL.equals(u.getProtocol())) {
@@ -264,6 +353,7 @@ public void notify(List<URL> urls) {
         return result;
     }
 
+    @Override
     public void register(URL url) {
         if (url == null) {
             throw new IllegalArgumentException("register url == null");
@@ -271,9 +361,11 @@ public void register(URL url) {
         if (logger.isInfoEnabled()) {
             logger.info("Register: " + url);
         }
+        // 添加到 registered 集合
         registered.add(url);
     }
 
+    @Override
     public void unregister(URL url) {
         if (url == null) {
             throw new IllegalArgumentException("unregister url == null");
@@ -281,9 +373,11 @@ public void unregister(URL url) {
         if (logger.isInfoEnabled()) {
             logger.info("Unregister: " + url);
         }
+        // 移除出 registered 集合
         registered.remove(url);
     }
 
+    @Override
     public void subscribe(URL url, NotifyListener listener) {
         if (url == null) {
             throw new IllegalArgumentException("subscribe url == null");
@@ -294,6 +388,7 @@ public void subscribe(URL url, NotifyListener listener) {
         if (logger.isInfoEnabled()) {
             logger.info("Subscribe: " + url);
         }
+        // 添加到 subscribed 集合
         Set<NotifyListener> listeners = subscribed.get(url);
         if (listeners == null) {
             subscribed.putIfAbsent(url, new ConcurrentHashSet<NotifyListener>());
@@ -302,6 +397,7 @@ public void subscribe(URL url, NotifyListener listener) {
         listeners.add(listener);
     }
 
+    @Override
     public void unsubscribe(URL url, NotifyListener listener) {
         if (url == null) {
             throw new IllegalArgumentException("unsubscribe url == null");
@@ -312,14 +408,20 @@ public void unsubscribe(URL url, NotifyListener listener) {
         if (logger.isInfoEnabled()) {
             logger.info("Unsubscribe: " + url);
         }
+        // 移除出 subscribed 集合
         Set<NotifyListener> listeners = subscribed.get(url);
         if (listeners != null) {
             listeners.remove(listener);
         }
     }
 
+    /**
+     * 恢复注册和订阅
+     *
+     * @throws Exception 发生异常
+     */
     protected void recover() throws Exception {
-        // register
+        // register 恢复注册
         Set<URL> recoverRegistered = new HashSet<URL>(getRegistered());
         if (!recoverRegistered.isEmpty()) {
             if (logger.isInfoEnabled()) {
@@ -329,7 +431,7 @@ protected void recover() throws Exception {
                 register(url);
             }
         }
-        // subscribe
+        // subscribe 恢复订阅
         Map<URL, Set<NotifyListener>> recoverSubscribed = new HashMap<URL, Set<NotifyListener>>(getSubscribed());
         if (!recoverSubscribed.isEmpty()) {
             if (logger.isInfoEnabled()) {
@@ -344,16 +446,21 @@ protected void recover() throws Exception {
         }
     }
 
+    /**
+     * 通知监听器,URL 变化结果。
+     *
+     * @param urls 通知的 URL 变化结果(全量数据)
+     */
     protected void notify(List<URL> urls) {
         if (urls == null || urls.isEmpty()) return;
-
+        // 循环 `subscribed` ,通知监听器们
         for (Map.Entry<URL, Set<NotifyListener>> entry : getSubscribed().entrySet()) {
             URL url = entry.getKey();
-
+            // 匹配
             if (!UrlUtils.isMatch(url, urls.get(0))) {
                 continue;
             }
-
+            // 通知监听器
             Set<NotifyListener> listeners = entry.getValue();
             if (listeners != null) {
                 for (NotifyListener listener : listeners) {
@@ -367,7 +474,16 @@ protected void notify(List<URL> urls) {
         }
     }
 
-    protected void notify(URL url, NotifyListener listener, List<URL> urls) {
+    /**
+     * 通知监听器,URL 变化结果。
+     *
+     * 数据流向 `urls` => {@link #notified} => {@link #properties} => {@link #file}
+     *
+     * @param url 消费者 URL
+     * @param listener 监听器
+     * @param urls 通知的 URL 变化结果(全量数据)
+     */
+    protected void  notify(URL url, NotifyListener listener, List<URL> urls) {
         if (url == null) {
             throw new IllegalArgumentException("notify url == null");
         }
@@ -382,6 +498,8 @@ protected void notify(URL url, NotifyListener listener, List<URL> urls) {
         if (logger.isInfoEnabled()) {
             logger.info("Notify urls for subscribe url " + url + ", urls: " + urls);
         }
+        // 将 `urls` 按照 `url.parameter.category` 分类,添加到集合
+        // 注意,特殊情况,使用 curator 连接 Zookeeper 时,若是服务消费者,连接断开,会出现 category=providers,configurations,routes
         Map<String, List<URL>> result = new HashMap<String, List<URL>>();
         for (URL u : urls) {
             if (UrlUtils.isMatch(url, u)) {
@@ -397,26 +515,38 @@ protected void notify(URL url, NotifyListener listener, List<URL> urls) {
         if (result.size() == 0) {
             return;
         }
+        // 获得消费者 URL 对应的在 `notified` 中,通知的 URL 变化结果(全量数据)
         Map<String, List<URL>> categoryNotified = notified.get(url);
         if (categoryNotified == null) {
             notified.putIfAbsent(url, new ConcurrentHashMap<String, List<URL>>());
             categoryNotified = notified.get(url);
         }
+        // 处理通知的 URL 变化结果(全量数据)
         for (Map.Entry<String, List<URL>> entry : result.entrySet()) {
             String category = entry.getKey();
             List<URL> categoryList = entry.getValue();
+            // 覆盖到 `notified`
+            // 当某个分类的数据为空时,会依然有 urls 。其中 `urls[0].protocol = empty` ,通过这样的方式,处理所有服务提供者为空的情况。
             categoryNotified.put(category, categoryList);
+            // 保存到文件
             saveProperties(url);
+            // 通知监听器
             listener.notify(categoryList);
         }
     }
 
+    /**
+     * 保存单个消费者 URL 对应,在 `notified` 的数据,到文件。
+     *
+     * @param url 消费者 URL
+     */
     private void saveProperties(URL url) {
         if (file == null) {
             return;
         }
 
         try {
+            // 拼接 URL
             StringBuilder buf = new StringBuilder();
             Map<String, List<URL>> categoryNotified = notified.get(url);
             if (categoryNotified != null) {
@@ -429,8 +559,11 @@ private void saveProperties(URL url) {
                     }
                 }
             }
+            // 设置到 properties 中
             properties.setProperty(url.getServiceKey(), buf.toString());
+            // 增加数据版本号
             long version = lastCacheChanged.incrementAndGet();
+            // 保存到文件
             if (syncSaveFile) {
                 doSaveProperties(version);
             } else {
@@ -441,20 +574,24 @@ private void saveProperties(URL url) {
         }
     }
 
+    /**
+     * 取消注册和订阅
+     */
     public void destroy() {
+        // 已销毁,跳过
         if (!destroyed.compareAndSet(false, true)) {
             return;
         }
-
         if (logger.isInfoEnabled()) {
             logger.info("Destroy registry:" + getUrl());
         }
+        // 取消注册
         Set<URL> destroyRegistered = new HashSet<URL>(getRegistered());
         if (!destroyRegistered.isEmpty()) {
             for (URL url : new HashSet<URL>(getRegistered())) {
                 if (url.getParameter(Constants.DYNAMIC_KEY, true)) {
                     try {
-                        unregister(url);
+                        unregister(url); // 取消
                         if (logger.isInfoEnabled()) {
                             logger.info("Destroy unregister url " + url);
                         }
@@ -464,13 +601,14 @@ public void destroy() {
                 }
             }
         }
+        // 取消订阅
         Map<URL, Set<NotifyListener>> destroySubscribed = new HashMap<URL, Set<NotifyListener>>(getSubscribed());
         if (!destroySubscribed.isEmpty()) {
             for (Map.Entry<URL, Set<NotifyListener>> entry : destroySubscribed.entrySet()) {
                 URL url = entry.getKey();
                 for (NotifyListener listener : entry.getValue()) {
                     try {
-                        unsubscribe(url, listener);
+                        unsubscribe(url, listener); // 取消
                         if (logger.isInfoEnabled()) {
                             logger.info("Destroy unsubscribe url " + url);
                         }
@@ -486,7 +624,14 @@ public String toString() {
         return getUrl().toString();
     }
 
+    /**
+     * 保存配置的 Runnable
+     */
     private class SaveProperties implements Runnable {
+
+        /**
+         * 数据版本号
+         */
         private long version;
 
         private SaveProperties(long version) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/AbstractRegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/AbstractRegistryFactory.java
index 1fa4429a2d..176c52cde6 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/AbstractRegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/AbstractRegistryFactory.java
@@ -33,6 +33,8 @@
 /**
  * AbstractRegistryFactory. (SPI, Singleton, ThreadSafe)
  *
+ * 注册中心抽象类
+ *
  * @see com.alibaba.dubbo.registry.RegistryFactory
  */
 public abstract class AbstractRegistryFactory implements RegistryFactory {
@@ -43,6 +45,11 @@
     // The lock for the acquisition process of the registry
     private static final ReentrantLock LOCK = new ReentrantLock();
 
+    /**
+     * Registry 集合
+     *
+     * key:{@link URL#toServiceString()}
+     */
     // Registry Collection Map<RegistryAddress, Registry>
     private static final Map<String, Registry> REGISTRIES = new ConcurrentHashMap<String, Registry>();
 
@@ -56,6 +63,8 @@
     }
 
     /**
+     * 销毁
+     *
      * Close all created registries
      */
     // TODO: 2017/8/30 to move somewhere else better
@@ -63,9 +72,11 @@ public static void destroyAll() {
         if (LOGGER.isInfoEnabled()) {
             LOGGER.info("Close all registries " + getRegistries());
         }
+        // 获得锁
         // Lock up the registry shutdown process
         LOCK.lock();
         try {
+            // 销毁
             for (Registry registry : getRegistries()) {
                 try {
                     registry.destroy();
@@ -73,37 +84,59 @@ public static void destroyAll() {
                     LOGGER.error(e.getMessage(), e);
                 }
             }
+            // 清空缓存
             REGISTRIES.clear();
         } finally {
+            // 释放锁
             // Release the lock
             LOCK.unlock();
         }
     }
 
+    /**
+     * 获得注册中心 Registry 对象
+     *
+     * @param url 注册中心地址,不允许为空
+     * @return Registry 对象
+     */
+    @Override
     public Registry getRegistry(URL url) {
-        url = url.setPath(RegistryService.class.getName())
-                .addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName())
-                .removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY);
+        // 修改 URL
+        url = url.setPath(RegistryService.class.getName()) // + `path`
+                .addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName()) // + `parameters.interface`
+                .removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY); // - `export`
+        // 计算 key
         String key = url.toServiceString();
+        // 获得锁
         // Lock the registry access process to ensure a single instance of the registry
         LOCK.lock();
         try {
+            // 从缓存中获得 Registry 对象
             Registry registry = REGISTRIES.get(key);
             if (registry != null) {
                 return registry;
             }
+            // 缓存不存在,进行创建 Registry 对象
             registry = createRegistry(url);
             if (registry == null) {
                 throw new IllegalStateException("Can not create registry " + url);
             }
+            // 添加到缓存
             REGISTRIES.put(key, registry);
             return registry;
         } finally {
+            // 释放锁
             // Release the lock
             LOCK.unlock();
         }
     }
 
+    /**
+     * 创建 Registry 对象
+     *
+     * @param url 注册中心地址
+     * @return Registry 对象
+     */
     protected abstract Registry createRegistry(URL url);
 
 }
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ConsumerInvokerWrapper.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ConsumerInvokerWrapper.java
index e0cb8e1079..7401e57783 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ConsumerInvokerWrapper.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ConsumerInvokerWrapper.java
@@ -24,13 +24,31 @@
 import com.alibaba.dubbo.rpc.RpcException;
 
 /**
+ * 消费者 Invoker Wrapper
+ *
  * @date 2017/11/23
  */
 public class ConsumerInvokerWrapper<T> implements Invoker {
+
+    /**
+     * Invoker 对象
+     */
     private Invoker<T> invoker;
+    /**
+     * 原始 URL
+     */
     private URL originUrl;
+    /**
+     * 注册中心 URL
+     */
     private URL registryUrl;
+    /**
+     * 消费者 URL
+     */
     private URL consumerUrl;
+    /**
+     * 注册中心 Directory
+     */
     private RegistryDirectory registryDirectory;
 
     public ConsumerInvokerWrapper(Invoker<T> invoker, URL registryUrl, URL consumerUrl, RegistryDirectory registryDirectory) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/FailbackRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/FailbackRegistry.java
index 207fd49c4d..70ddeb980a 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/FailbackRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/FailbackRegistry.java
@@ -39,30 +39,52 @@
 /**
  * FailbackRegistry. (SPI, Prototype, ThreadSafe)
  *
+ * 支持失败重试的 Registry 抽象类
  */
 public abstract class FailbackRegistry extends AbstractRegistry {
 
+    /**
+     * 定时任务执行器
+     */
     // Scheduled executor service
     private final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("DubboRegistryFailedRetryTimer", true));
 
+    /**
+     * 失败重试定时器,定时检查是否有请求失败,如有,无限次重试
+     */
     // Timer for failure retry, regular check if there is a request for failure, and if there is, an unlimited retry
     private final ScheduledFuture<?> retryFuture;
-
+    /**
+     * 失败发起注册失败的 URL 集合
+     */
     private final Set<URL> failedRegistered = new ConcurrentHashSet<URL>();
-
+    /**
+     * 失败取消注册失败的 URL 集合
+     */
     private final Set<URL> failedUnregistered = new ConcurrentHashSet<URL>();
-
+    /**
+     * 失败发起订阅失败的监听器集合
+     */
     private final ConcurrentMap<URL, Set<NotifyListener>> failedSubscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>();
-
+    /**
+     * 失败取消订阅失败的监听器集合
+     */
     private final ConcurrentMap<URL, Set<NotifyListener>> failedUnsubscribed = new ConcurrentHashMap<URL, Set<NotifyListener>>();
-
+    /**
+     * 失败通知通知的 URL 集合
+     */
     private final ConcurrentMap<URL, Map<NotifyListener, List<URL>>> failedNotified = new ConcurrentHashMap<URL, Map<NotifyListener, List<URL>>>();
 
+    /**
+     * 是否销毁
+     */
     private AtomicBoolean destroyed = new AtomicBoolean(false);
 
     public FailbackRegistry(URL url) {
         super(url);
+        // 重试频率,单位:毫秒
         int retryPeriod = url.getParameter(Constants.REGISTRY_RETRY_PERIOD_KEY, Constants.DEFAULT_REGISTRY_RETRY_PERIOD);
+        // 创建失败重试定时器
         this.retryFuture = retryExecutor.scheduleWithFixedDelay(new Runnable() {
             public void run() {
                 // Check and connect to the registry
@@ -99,6 +121,12 @@ public void run() {
         return failedNotified;
     }
 
+    /**
+     * 添加到 `failedSubscribed`
+     *
+     * @param url
+     * @param listener
+     */
     private void addFailedSubscribed(URL url, NotifyListener listener) {
         Set<NotifyListener> listeners = failedSubscribed.get(url);
         if (listeners == null) {
@@ -108,15 +136,24 @@ private void addFailedSubscribed(URL url, NotifyListener listener) {
         listeners.add(listener);
     }
 
+    /**
+     * 移除出 `failedSubscribed` `failedUnsubscribed` `failedNotified`
+     *
+     * @param url URL
+     * @param listener 监听器
+     */
     private void removeFailedSubscribed(URL url, NotifyListener listener) {
+        // 移除出 `failedSubscribed`
         Set<NotifyListener> listeners = failedSubscribed.get(url);
         if (listeners != null) {
             listeners.remove(listener);
         }
+        // 移除出 `failedUnsubscribed`
         listeners = failedUnsubscribed.get(url);
         if (listeners != null) {
             listeners.remove(listener);
         }
+        // 移除出 `failedNotified`
         Map<NotifyListener, List<URL>> notified = failedNotified.get(url);
         if (notified != null) {
             notified.remove(listener);
@@ -125,22 +162,27 @@ private void removeFailedSubscribed(URL url, NotifyListener listener) {
 
     @Override
     public void register(URL url) {
+        // 已销毁,跳过
         if (destroyed.get()){
             return;
         }
+        // 添加到 `registered` 变量
         super.register(url);
+        // 移除出 `failedRegistered` `failedUnregistered` 变量
         failedRegistered.remove(url);
         failedUnregistered.remove(url);
+        // 向注册中心发送注册请求
         try {
             // Sending a registration request to the server side
             doRegister(url);
         } catch (Exception e) {
             Throwable t = e;
 
+            // 如果开启了启动时检测,则直接抛出异常
             // If the startup detection is opened, the Exception is thrown directly.
             boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
                     && url.getParameter(Constants.CHECK_KEY, true)
-                    && !Constants.CONSUMER_PROTOCOL.equals(url.getProtocol());
+                    && !Constants.CONSUMER_PROTOCOL.equals(url.getProtocol()); // 非消费者。消费者会在 `ReferenceConfig#createProxy(...)` 方法中,调用 `Invoker#avalible()` 方法,进行检查。
             boolean skipFailback = t instanceof SkipFailbackWrapperException;
             if (check || skipFailback) {
                 if (skipFailback) {
@@ -151,6 +193,7 @@ public void register(URL url) {
                 logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t);
             }
 
+            // 将失败的注册请求记录到 `failedRegistered`,定时重试
             // Record a failed registration request to a failed list, retry regularly
             failedRegistered.add(url);
         }
@@ -158,18 +201,23 @@ public void register(URL url) {
 
     @Override
     public void unregister(URL url) {
+        // 已销毁,跳过
         if (destroyed.get()){
             return;
         }
+        // 移除出 `registered` 变量
         super.unregister(url);
+        // 移除出 `failedRegistered` `failedUnregistered` 变量
         failedRegistered.remove(url);
         failedUnregistered.remove(url);
+        // 向注册中心发送取消注册请求
         try {
             // Sending a cancellation request to the server side
             doUnregister(url);
         } catch (Exception e) {
             Throwable t = e;
 
+            // 如果开启了启动时检测,则直接抛出异常
             // If the startup detection is opened, the Exception is thrown directly.
             boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
                     && url.getParameter(Constants.CHECK_KEY, true)
@@ -184,6 +232,7 @@ public void unregister(URL url) {
                 logger.error("Failed to uregister " + url + ", waiting for retry, cause: " + t.getMessage(), t);
             }
 
+            // 将失败的取消注册请求记录到 `failedUnregistered`,定时重试
             // Record a failed registration request to a failed list, retry regularly
             failedUnregistered.add(url);
         }
@@ -191,22 +240,28 @@ public void unregister(URL url) {
 
     @Override
     public void subscribe(URL url, NotifyListener listener) {
+        // 已销毁,跳过
         if (destroyed.get()){
             return;
         }
+        // 移除出 `subscribed` 变量
         super.subscribe(url, listener);
+        // 移除出 `failedSubscribed` `failedUnsubscribed` `failedNotified`
         removeFailedSubscribed(url, listener);
+        // 向注册中心发送订阅请求
         try {
             // Sending a subscription request to the server side
             doSubscribe(url, listener);
         } catch (Exception e) {
             Throwable t = e;
 
+            // 如果有缓存的 URL 集合,进行通知。后续订阅成功后,会使用最新的 URL 集合,进行通知。
             List<URL> urls = getCacheUrls(url);
             if (urls != null && !urls.isEmpty()) {
                 notify(url, listener, urls);
                 logger.error("Failed to subscribe " + url + ", Using cached list: " + urls + " from cache file: " + getUrl().getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/dubbo-registry-" + url.getHost() + ".cache") + ", cause: " + t.getMessage(), t);
             } else {
+                // 如果开启了启动时检测,则直接抛出异常
                 // If the startup detection is opened, the Exception is thrown directly.
                 boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
                         && url.getParameter(Constants.CHECK_KEY, true);
@@ -221,6 +276,7 @@ public void subscribe(URL url, NotifyListener listener) {
                 }
             }
 
+            // 将失败的订阅请求记录到 `failedSubscribed`,定时重试
             // Record a failed registration request to a failed list, retry regularly
             addFailedSubscribed(url, listener);
         }
@@ -228,17 +284,22 @@ public void subscribe(URL url, NotifyListener listener) {
 
     @Override
     public void unsubscribe(URL url, NotifyListener listener) {
+        // 已销毁,跳过
         if (destroyed.get()){
             return;
         }
+        // 移除出 `unsubscribed` 变量
         super.unsubscribe(url, listener);
+        // 移除出 `failedSubscribed` `failedUnsubscribed` `failedNotified`
         removeFailedSubscribed(url, listener);
+        // 向注册中心发送取消订阅请求
         try {
             // Sending a canceling subscription request to the server side
             doUnsubscribe(url, listener);
         } catch (Exception e) {
             Throwable t = e;
 
+            // 如果开启了启动时检测,则直接抛出异常
             // If the startup detection is opened, the Exception is thrown directly.
             boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
                     && url.getParameter(Constants.CHECK_KEY, true);
@@ -252,6 +313,7 @@ public void unsubscribe(URL url, NotifyListener listener) {
                 logger.error("Failed to unsubscribe " + url + ", waiting for retry, cause: " + t.getMessage(), t);
             }
 
+            // 将失败的订阅请求记录到 `failedUnsubscribed`,定时重试
             // Record a failed registration request to a failed list, retry regularly
             Set<NotifyListener> listeners = failedUnsubscribed.get(url);
             if (listeners == null) {
@@ -270,9 +332,11 @@ protected void notify(URL url, NotifyListener listener, List<URL> urls) {
         if (listener == null) {
             throw new IllegalArgumentException("notify listener == null");
         }
+        // 通知监听器
         try {
             doNotify(url, listener, urls);
         } catch (Exception t) {
+            // 将失败的通知记录到 `failedNotified`,定时重试
             // Record a failed registration request to a failed list, retry regularly
             Map<NotifyListener, List<URL>> listeners = failedNotified.get(url);
             if (listeners == null) {
@@ -290,7 +354,7 @@ protected void doNotify(URL url, NotifyListener listener, List<URL> urls) {
 
     @Override
     protected void recover() throws Exception {
-        // register
+        // register 恢复注册,添加到 `failedRegistered` ,定时重试
         Set<URL> recoverRegistered = new HashSet<URL>(getRegistered());
         if (!recoverRegistered.isEmpty()) {
             if (logger.isInfoEnabled()) {
@@ -300,7 +364,7 @@ protected void recover() throws Exception {
                 failedRegistered.add(url);
             }
         }
-        // subscribe
+        // subscribe 恢复订阅,添加到 `failedSubscribed` ,定时重试
         Map<URL, Set<NotifyListener>> recoverSubscribed = new HashMap<URL, Set<NotifyListener>>(getSubscribed());
         if (!recoverSubscribed.isEmpty()) {
             if (logger.isInfoEnabled()) {
@@ -315,10 +379,14 @@ protected void recover() throws Exception {
         }
     }
 
+    /**
+     * 重试
+     */
     // Retry the failed actions
     protected void retry() {
+        // 重试执行注册
         if (!failedRegistered.isEmpty()) {
-            Set<URL> failed = new HashSet<URL>(failedRegistered);
+            Set<URL> failed = new HashSet<URL>(failedRegistered); // 避免并发冲突
             if (failed.size() > 0) {
                 if (logger.isInfoEnabled()) {
                     logger.info("Retry register " + failed);
@@ -326,7 +394,9 @@ protected void retry() {
                 try {
                     for (URL url : failed) {
                         try {
+                            // 执行注册
                             doRegister(url);
+                            // 移除出 `failedRegistered`
                             failedRegistered.remove(url);
                         } catch (Throwable t) { // Ignore all the exceptions and wait for the next retry
                             logger.warn("Failed to retry register " + failed + ", waiting for again, cause: " + t.getMessage(), t);
@@ -337,8 +407,9 @@ protected void retry() {
                 }
             }
         }
+        // 重试执行取消注册
         if (!failedUnregistered.isEmpty()) {
-            Set<URL> failed = new HashSet<URL>(failedUnregistered);
+            Set<URL> failed = new HashSet<URL>(failedUnregistered); // 避免并发冲突
             if (!failed.isEmpty()) {
                 if (logger.isInfoEnabled()) {
                     logger.info("Retry unregister " + failed);
@@ -346,7 +417,9 @@ protected void retry() {
                 try {
                     for (URL url : failed) {
                         try {
+                            // 执行取消注册
                             doUnregister(url);
+                            // 移除出 `failedUnregistered`
                             failedUnregistered.remove(url);
                         } catch (Throwable t) { // Ignore all the exceptions and wait for the next retry
                             logger.warn("Failed to retry unregister  " + failed + ", waiting for again, cause: " + t.getMessage(), t);
@@ -357,8 +430,9 @@ protected void retry() {
                 }
             }
         }
+        // 重试执行注册
         if (!failedSubscribed.isEmpty()) {
-            Map<URL, Set<NotifyListener>> failed = new HashMap<URL, Set<NotifyListener>>(failedSubscribed);
+            Map<URL, Set<NotifyListener>> failed = new HashMap<URL, Set<NotifyListener>>(failedSubscribed); // 避免并发冲突
             for (Map.Entry<URL, Set<NotifyListener>> entry : new HashMap<URL, Set<NotifyListener>>(failed).entrySet()) {
                 if (entry.getValue() == null || entry.getValue().size() == 0) {
                     failed.remove(entry.getKey());
@@ -374,7 +448,9 @@ protected void retry() {
                         Set<NotifyListener> listeners = entry.getValue();
                         for (NotifyListener listener : listeners) {
                             try {
+                                // 执行注册
                                 doSubscribe(url, listener);
+                                // 移除出监听器
                                 listeners.remove(listener);
                             } catch (Throwable t) { // Ignore all the exceptions and wait for the next retry
                                 logger.warn("Failed to retry subscribe " + failed + ", waiting for again, cause: " + t.getMessage(), t);
@@ -386,6 +462,7 @@ protected void retry() {
                 }
             }
         }
+        // 重试执行取消注册
         if (!failedUnsubscribed.isEmpty()) {
             Map<URL, Set<NotifyListener>> failed = new HashMap<URL, Set<NotifyListener>>(failedUnsubscribed);
             for (Map.Entry<URL, Set<NotifyListener>> entry : new HashMap<URL, Set<NotifyListener>>(failed).entrySet()) {
@@ -403,7 +480,9 @@ protected void retry() {
                         Set<NotifyListener> listeners = entry.getValue();
                         for (NotifyListener listener : listeners) {
                             try {
+                                // 执行取消注册
                                 doUnsubscribe(url, listener);
+                                // 移除出监听器
                                 listeners.remove(listener);
                             } catch (Throwable t) { // Ignore all the exceptions and wait for the next retry
                                 logger.warn("Failed to retry unsubscribe " + failed + ", waiting for again, cause: " + t.getMessage(), t);
@@ -415,6 +494,7 @@ protected void retry() {
                 }
             }
         }
+        // 重试执行通知监听器
         if (!failedNotified.isEmpty()) {
             Map<URL, Map<NotifyListener, List<URL>>> failed = new HashMap<URL, Map<NotifyListener, List<URL>>>(failedNotified);
             for (Map.Entry<URL, Map<NotifyListener, List<URL>>> entry : new HashMap<URL, Map<NotifyListener, List<URL>>>(failed).entrySet()) {
@@ -432,7 +512,9 @@ protected void retry() {
                             try {
                                 NotifyListener listener = entry.getKey();
                                 List<URL> urls = entry.getValue();
+                                // 通知监听器
                                 listener.notify(urls);
+                                // 移除出监听器
                                 values.remove(listener);
                             } catch (Throwable t) { // Ignore all the exceptions and wait for the next retry
                                 logger.warn("Failed to retry notify " + failed + ", waiting for again, cause: " + t.getMessage(), t);
@@ -461,14 +543,9 @@ public void destroy() {
 
     // TODO: 2017/8/30 to abstract this method
     protected boolean canDestroy(){
-        if (destroyed.compareAndSet(false, true)) {
-            return true;
-        }else{
-            return false;
-        }
+        return destroyed.compareAndSet(false, true);
     }
 
-
     // ==== Template method ====
 
     protected abstract void doRegister(URL url);
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ProviderConsumerRegTable.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ProviderConsumerRegTable.java
index cd408ca405..2b7a956547 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ProviderConsumerRegTable.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ProviderConsumerRegTable.java
@@ -27,15 +27,40 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
+ * 服务提供者和消费者注册表
+ *
+ * 用于在线运维命令 QOS 使用,参见文档:http://dubbo.io/books/dubbo-user-book/references/qos.html
+ *
  * @date 2017/11/23
  */
 public class ProviderConsumerRegTable {
+
+    /**
+     * 服务提供者 Invoker 集合
+     *
+     * key:服务提供者 URL 服务键
+     */
     public static ConcurrentHashMap<String, Set<ProviderInvokerWrapper>> providerInvokers = new ConcurrentHashMap<String, Set<ProviderInvokerWrapper>>();
+    /**
+     * 服务消费者 Invoker 集合
+     *
+     * key:服务消费者 URL 服务键
+     */
     public static ConcurrentHashMap<String, Set<ConsumerInvokerWrapper>> consumerInvokers = new ConcurrentHashMap<String, Set<ConsumerInvokerWrapper>>();
 
+    /**
+     * 注册 Provider Invoker
+     *
+     * @param invoker invoker 对象
+     * @param registryUrl 注册中心 URL
+     * @param providerUrl 服务提供者 URL
+     */
     public static void registerProvider(Invoker invoker, URL registryUrl, URL providerUrl) {
+        // 创建 ProviderInvokerWrapper 对象
         ProviderInvokerWrapper wrapperInvoker = new ProviderInvokerWrapper(invoker, registryUrl, providerUrl);
+        // 服务键
         String serviceUniqueName = providerUrl.getServiceKey();
+        // 添加到集合
         Set<ProviderInvokerWrapper> invokers = providerInvokers.get(serviceUniqueName);
         if (invokers == null) {
             providerInvokers.putIfAbsent(serviceUniqueName, new ConcurrentHashSet<ProviderInvokerWrapper>());
@@ -44,6 +69,12 @@ public static void registerProvider(Invoker invoker, URL registryUrl, URL provid
         invokers.add(wrapperInvoker);
     }
 
+    /**
+     * 获得指定服务键的 Provider Invoker 集合
+     *
+     * @param serviceUniqueName 服务键
+     * @return 集合
+     */
     public static Set<ProviderInvokerWrapper> getProviderInvoker(String serviceUniqueName) {
         Set<ProviderInvokerWrapper> invokers = providerInvokers.get(serviceUniqueName);
         if (invokers == null) {
@@ -52,30 +83,48 @@ public static void registerProvider(Invoker invoker, URL registryUrl, URL provid
         return invokers;
     }
 
+    /**
+     * 获得服务提供者对应的 Invoker Wrapper 对象
+     *
+     * @param invoker 服务提供者 Invoker
+     * @return Invoker Wrapper 对象
+     */
     public static ProviderInvokerWrapper getProviderWrapper(Invoker invoker) {
+        // 获得服务提供者 URL
         URL providerUrl = invoker.getUrl();
         if (Constants.REGISTRY_PROTOCOL.equals(providerUrl.getProtocol())) {
             providerUrl = URL.valueOf(providerUrl.getParameterAndDecoded(Constants.EXPORT_KEY));
         }
+        // 获得指定的 Provider Invoker 集合
         String serviceUniqueName = providerUrl.getServiceKey();
         Set<ProviderInvokerWrapper> invokers = providerInvokers.get(serviceUniqueName);
         if (invokers == null) {
             return null;
         }
-
+        // 获得 invoker 对应的 ProviderInvokerWrapper 对象
         for (ProviderInvokerWrapper providerWrapper : invokers) {
             Invoker providerInvoker = providerWrapper.getInvoker();
             if (providerInvoker == invoker) {
                 return providerWrapper;
             }
         }
-
         return null;
     }
 
-    public static void registerConsuemr(Invoker invoker, URL registryUrl, URL consumerUrl, RegistryDirectory registryDirectory) {
+    /**
+     * 注册 Consumer Invoker
+     *
+     * @param invoker invoker 对象
+     * @param registryUrl 注册中心 URL
+     * @param consumerUrl 服务消费者 URL
+     * @param registryDirectory 注册中心 Directory
+     */
+    public static void registerConsumer(Invoker invoker, URL registryUrl, URL consumerUrl, RegistryDirectory registryDirectory) {
+        // 创建 ConsumerInvokerWrapper 对象
         ConsumerInvokerWrapper wrapperInvoker = new ConsumerInvokerWrapper(invoker, registryUrl, consumerUrl, registryDirectory);
+        // 服务键
         String serviceUniqueName = consumerUrl.getServiceKey();
+        // 添加到集合
         Set<ConsumerInvokerWrapper> invokers = consumerInvokers.get(serviceUniqueName);
         if (invokers == null) {
             consumerInvokers.putIfAbsent(serviceUniqueName, new ConcurrentHashSet<ConsumerInvokerWrapper>());
@@ -84,6 +133,12 @@ public static void registerConsuemr(Invoker invoker, URL registryUrl, URL consum
         invokers.add(wrapperInvoker);
     }
 
+    /**
+     * 获得指定服务键的 Consumer Invoker 集合
+     *
+     * @param serviceUniqueName 服务键
+     * @return 集合
+     */
     public static Set<ConsumerInvokerWrapper> getConsumerInvoker(String serviceUniqueName) {
         Set<ConsumerInvokerWrapper> invokers = consumerInvokers.get(serviceUniqueName);
         if (invokers == null) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ProviderInvokerWrapper.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ProviderInvokerWrapper.java
index b60fdf5d65..6d57bb3c48 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ProviderInvokerWrapper.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/support/ProviderInvokerWrapper.java
@@ -23,13 +23,31 @@
 import com.alibaba.dubbo.rpc.RpcException;
 
 /**
+ * 服务提供者 Invoker Wrapper
+ *
  * @date 2017/11/23
  */
 public class ProviderInvokerWrapper<T> implements Invoker {
+
+    /**
+     * Invoker 对象
+     */
     private Invoker<T> invoker;
+    /**
+     * 原始 URL
+     */
     private URL originUrl;
+    /**
+     * 注册中心 URL
+     */
     private URL registryUrl;
+    /**
+     * 服务提供者 URL
+     */
     private URL providerUrl;
+    /**
+     * 是否注册
+     */
     private volatile boolean isReg;
 
     public ProviderInvokerWrapper(Invoker<T> invoker,URL registryUrl,URL providerUrl) {
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/com/alibaba/dubbo/registry/zookeeper/ZookeeperRegistry.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/com/alibaba/dubbo/registry/zookeeper/ZookeeperRegistry.java
index dcce7e4d49..47557472ce 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/com/alibaba/dubbo/registry/zookeeper/ZookeeperRegistry.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/com/alibaba/dubbo/registry/zookeeper/ZookeeperRegistry.java
@@ -39,21 +39,36 @@
 /**
  * ZookeeperRegistry
  *
+ * Zookeeper Registry 实现类
  */
 public class ZookeeperRegistry extends FailbackRegistry {
 
     private final static Logger logger = LoggerFactory.getLogger(ZookeeperRegistry.class);
 
+    /**
+     * 默认端口
+     */
     private final static int DEFAULT_ZOOKEEPER_PORT = 2181;
-
+    /**
+     * 默认 Zookeeper 根节点
+     */
     private final static String DEFAULT_ROOT = "dubbo";
 
+    /**
+     * Zookeeper 根节点
+     */
     private final String root;
-
+    /**
+     * Service 接口全名集合
+     */
     private final Set<String> anyServices = new ConcurrentHashSet<String>();
-
+    /**
+     * 监听器集合
+     */
     private final ConcurrentMap<URL, ConcurrentMap<NotifyListener, ChildListener>> zkListeners = new ConcurrentHashMap<URL, ConcurrentMap<NotifyListener, ChildListener>>();
-
+    /**
+     * Zookeeper 客户端
+     */
     private final ZookeeperClient zkClient;
 
     public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
@@ -61,12 +76,15 @@ public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
         if (url.isAnyHost()) {
             throw new IllegalStateException("registry address == null");
         }
-        String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
+        // 获得 Zookeeper 根节点
+        String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT); // `url.parameters.group` 参数值
         if (!group.startsWith(Constants.PATH_SEPARATOR)) {
             group = Constants.PATH_SEPARATOR + group;
         }
         this.root = group;
+        // 创建 Zookeeper Client
         zkClient = zookeeperTransporter.connect(url);
+        // 添加 StateListener 对象。该监听器,在重连时,调用恢复方法。
         zkClient.addStateListener(new StateListener() {
             public void stateChanged(int state) {
                 if (state == RECONNECTED) {
@@ -80,6 +98,7 @@ public void stateChanged(int state) {
         });
     }
 
+    // 目前只有测试方法使用
     static String appendDefaultPort(String address) {
         if (address != null && address.length() > 0) {
             int i = address.indexOf(':');
@@ -92,10 +111,12 @@ static String appendDefaultPort(String address) {
         return address;
     }
 
+    @Override
     public boolean isAvailable() {
         return zkClient.isConnected();
     }
 
+    @Override
     public void destroy() {
         super.destroy();
         try {
@@ -105,6 +126,7 @@ public void destroy() {
         }
     }
 
+    @Override
     protected void doRegister(URL url) {
         try {
             zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true));
@@ -113,6 +135,7 @@ protected void doRegister(URL url) {
         }
     }
 
+    @Override
     protected void doUnregister(URL url) {
         try {
             zkClient.delete(toUrlPath(url));
@@ -121,21 +144,26 @@ protected void doUnregister(URL url) {
         }
     }
 
+    @Override
     protected void doSubscribe(final URL url, final NotifyListener listener) {
         try {
+            // 处理所有 Service 层的发起订阅,例如监控中心的订阅
             if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
                 String root = toRootPath();
+                // 获得 url 对应的监听器集合
                 ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
-                if (listeners == null) {
+                if (listeners == null) { // 不存在,进行创建
                     zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
                     listeners = zkListeners.get(url);
                 }
+                // 获得 ChildListener 对象
                 ChildListener zkListener = listeners.get(listener);
-                if (zkListener == null) {
+                if (zkListener == null) { // 不存在 ChildListener 对象,进行创建 ChildListener 对象
                     listeners.putIfAbsent(listener, new ChildListener() {
                         public void childChanged(String parentPath, List<String> currentChilds) {
                             for (String child : currentChilds) {
                                 child = URL.decode(child);
+                                // 新增 Service 接口全名时(即新增服务),发起该 Service 层的订阅
                                 if (!anyServices.contains(child)) {
                                     anyServices.add(child);
                                     subscribe(url.setPath(child).addParameters(Constants.INTERFACE_KEY, child,
@@ -146,8 +174,11 @@ public void childChanged(String parentPath, List<String> currentChilds) {
                     });
                     zkListener = listeners.get(listener);
                 }
+                // 创建 Service 节点。该节点为持久节点。
                 zkClient.create(root, false);
+                // 向 Zookeeper ,Service 节点,发起订阅
                 List<String> services = zkClient.addChildListener(root, zkListener);
+                // 首次全量数据获取完成时,循环 Service 接口全名数组,发起该 Service 层的订阅
                 if (services != null && !services.isEmpty()) {
                     for (String service : services) {
                         service = URL.decode(service);
@@ -156,29 +187,39 @@ public void childChanged(String parentPath, List<String> currentChilds) {
                                 Constants.CHECK_KEY, String.valueOf(false)), listener);
                     }
                 }
+            // 处理指定 Service 层的发起订阅,例如服务消费者的订阅
             } else {
+                // 子节点数据数组
                 List<URL> urls = new ArrayList<URL>();
+                // 循环分类数组
                 for (String path : toCategoriesPath(url)) {
+                    // 获得 url 对应的监听器集合
                     ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
-                    if (listeners == null) {
+                    if (listeners == null) { // 不存在,进行创建
                         zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
                         listeners = zkListeners.get(url);
                     }
+                    // 获得 ChildListener 对象
                     ChildListener zkListener = listeners.get(listener);
-                    if (zkListener == null) {
+                    if (zkListener == null) { // 不存在 ChildListener 对象,进行创建 ChildListener 对象
                         listeners.putIfAbsent(listener, new ChildListener() {
                             public void childChanged(String parentPath, List<String> currentChilds) {
+                                // 变更时,调用 `#notify(...)` 方法,回调 NotifyListener
                                 ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds));
                             }
                         });
                         zkListener = listeners.get(listener);
                     }
+                    // 创建 Type 节点。该节点为持久节点。
                     zkClient.create(path, false);
+                    // 向 Zookeeper ,PATH 节点,发起订阅
                     List<String> children = zkClient.addChildListener(path, zkListener);
+                    // 添加到 `urls` 中
                     if (children != null) {
                         urls.addAll(toUrlsWithEmpty(url, path, children));
                     }
                 }
+                // 首次全量数据获取完成时,调用 `#notify(...)` 方法,回调 NotifyListener
                 notify(url, listener, urls);
             }
         } catch (Throwable e) {
@@ -186,21 +227,25 @@ public void childChanged(String parentPath, List<String> currentChilds) {
         }
     }
 
+    @Override
     protected void doUnsubscribe(URL url, NotifyListener listener) {
         ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
         if (listeners != null) {
             ChildListener zkListener = listeners.get(listener);
             if (zkListener != null) {
+                // 向 Zookeeper ,移除订阅
                 zkClient.removeChildListener(toUrlPath(url), zkListener);
             }
         }
     }
 
+    @Override
     public List<URL> lookup(URL url) {
         if (url == null) {
             throw new IllegalArgumentException("lookup url == null");
         }
         try {
+            // 循环分类数组,获得所有的 URL 数组
             List<String> providers = new ArrayList<String>();
             for (String path : toCategoriesPath(url)) {
                 List<String> children = zkClient.getChildren(path);
@@ -208,12 +253,20 @@ protected void doUnsubscribe(URL url, NotifyListener listener) {
                     providers.addAll(children);
                 }
             }
+            // 匹配
             return toUrlsWithoutEmpty(url, providers);
         } catch (Throwable e) {
             throw new RpcException("Failed to lookup " + url + " from zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
         }
     }
 
+    /**
+     * 获得根目录
+     *
+     * Root
+     *
+     * @return 路径
+     */
     private String toRootDir() {
         if (root.equals(Constants.PATH_SEPARATOR)) {
             return root;
@@ -221,10 +274,23 @@ private String toRootDir() {
         return root + Constants.PATH_SEPARATOR;
     }
 
+    /**
+     * Root
+     *
+     * @return 根路径
+     */
     private String toRootPath() {
         return root;
     }
 
+    /**
+     * 获得服务路径
+     *
+     * Root + Type
+     *
+     * @param url URL
+     * @return 服务路径
+     */
     private String toServicePath(URL url) {
         String name = url.getServiceInterface();
         if (Constants.ANY_VALUE.equals(name)) {
@@ -233,14 +299,24 @@ private String toServicePath(URL url) {
         return toRootDir() + URL.encode(name);
     }
 
+    /**
+     * 获得分类路径数组
+     *
+     * Root + Service + Type
+     *
+     * @param url URL
+     * @return 分类路径数组
+     */
     private String[] toCategoriesPath(URL url) {
+        // 获得分类数组
         String[] categories;
-        if (Constants.ANY_VALUE.equals(url.getParameter(Constants.CATEGORY_KEY))) {
+        if (Constants.ANY_VALUE.equals(url.getParameter(Constants.CATEGORY_KEY))) { // * 时,
             categories = new String[]{Constants.PROVIDERS_CATEGORY, Constants.CONSUMERS_CATEGORY,
                     Constants.ROUTERS_CATEGORY, Constants.CONFIGURATORS_CATEGORY};
         } else {
             categories = url.getParameter(Constants.CATEGORY_KEY, new String[]{Constants.DEFAULT_CATEGORY});
         }
+        // 获得分类路径数组
         String[] paths = new String[categories.length];
         for (int i = 0; i < categories.length; i++) {
             paths[i] = toServicePath(url) + Constants.PATH_SEPARATOR + categories[i];
@@ -248,22 +324,47 @@ private String toServicePath(URL url) {
         return paths;
     }
 
+    /**
+     * 获得分类路径
+     *
+     * Root + Service + Type
+     *
+     * @param url URL
+     * @return 分类路径
+     */
     private String toCategoryPath(URL url) {
         return toServicePath(url) + Constants.PATH_SEPARATOR + url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
     }
 
+    /**
+     * 获得 URL 的路径
+     *
+     * Root + Service + Type + URL
+     *
+     * 被 {@link #doRegister(URL)} 和 {@link #doUnregister(URL)} 调用
+     *
+     * @param url URL
+     * @return 路径
+     */
     private String toUrlPath(URL url) {
         return toCategoryPath(url) + Constants.PATH_SEPARATOR + URL.encode(url.toFullString());
     }
 
+    /**
+     * 获得 providers 中,和 consumer 匹配的 URL 数组
+     *
+     * @param consumer 用于匹配 URL
+     * @param providers 被匹配的 URL 的字符串
+     * @return 匹配的 URL 数组
+     */
     private List<URL> toUrlsWithoutEmpty(URL consumer, List<String> providers) {
         List<URL> urls = new ArrayList<URL>();
         if (providers != null && !providers.isEmpty()) {
             for (String provider : providers) {
                 provider = URL.decode(provider);
-                if (provider.contains("://")) {
-                    URL url = URL.valueOf(provider);
-                    if (UrlUtils.isMatch(consumer, url)) {
+                if (provider.contains("://")) { // 是 url
+                    URL url = URL.valueOf(provider); // 将字符串转化成 URL
+                    if (UrlUtils.isMatch(consumer, url)) { // 匹配
                         urls.add(url);
                     }
                 }
@@ -272,8 +373,20 @@ private String toUrlPath(URL url) {
         return urls;
     }
 
+    /**
+     * 获得 providers 中,和 consumer 匹配的 URL 数组
+     *
+     * 若不存在匹配,则创建 `empty://` 的 URL返回。通过这样的方式,可以处理类似服务提供者为空的情况。
+     *
+     * @param consumer 用于匹配 URL
+     * @param path 被匹配的 URL 的字符串
+     * @param providers 匹配的 URL 数组
+     * @return 匹配的 URL 数组
+     */
     private List<URL> toUrlsWithEmpty(URL consumer, String path, List<String> providers) {
+        // 获得 providers 中,和 consumer 匹配的 URL 数组
         List<URL> urls = toUrlsWithoutEmpty(consumer, providers);
+        // 若不存在匹配,则创建 `empty://` 的 URL返回
         if (urls == null || urls.isEmpty()) {
             int i = path.lastIndexOf('/');
             String category = i < 0 ? path : path.substring(i + 1);
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/com/alibaba/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/com/alibaba/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java
index d0bba0a132..57d525a129 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/com/alibaba/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/com/alibaba/dubbo/registry/zookeeper/ZookeeperRegistryFactory.java
@@ -24,15 +24,27 @@
 /**
  * ZookeeperRegistryFactory.
  *
+ * Zookeeper Registry 工厂
  */
 public class ZookeeperRegistryFactory extends AbstractRegistryFactory {
 
+    /**
+     * Zookeeper 工厂
+     */
     private ZookeeperTransporter zookeeperTransporter;
 
+    /**
+     * 设置 Zookeeper 工厂
+     *
+     * 该方法,通过 Dubbo SPI 注入
+     *
+     * @param zookeeperTransporter Zookeeper 工厂对象
+     */
     public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
         this.zookeeperTransporter = zookeeperTransporter;
     }
 
+    @Override
     public Registry createRegistry(URL url) {
         return new ZookeeperRegistry(url, zookeeperTransporter);
     }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Channel.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Channel.java
index 771aefee93..2fdda13c41 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Channel.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Channel.java
@@ -21,7 +21,7 @@
 /**
  * Channel. (API/SPI, Prototype, ThreadSafe)
  *
- *
+ * 通道接口
  *
  * @see com.alibaba.dubbo.remoting.Client
  * @see com.alibaba.dubbo.remoting.Server#getChannels()
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/ChannelHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/ChannelHandler.java
index f93451422a..bba584a076 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/ChannelHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/ChannelHandler.java
@@ -22,6 +22,8 @@
 /**
  * ChannelHandler. (API, Prototype, ThreadSafe)
  *
+ * 通道处理器接口
+ *
  * @see com.alibaba.dubbo.remoting.Transporter#bind(com.alibaba.dubbo.common.URL, ChannelHandler)
  * @see com.alibaba.dubbo.remoting.Transporter#connect(com.alibaba.dubbo.common.URL, ChannelHandler)
  */
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Client.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Client.java
index a66e37b522..03d25d0ef0 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Client.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Client.java
@@ -20,6 +20,9 @@
 
 /**
  * Remoting Client. (API/SPI, Prototype, ThreadSafe)
+ *
+ * Client 接口
+ *
  * <p>
  * <a href="http://en.wikipedia.org/wiki/Client%E2%80%93server_model">Client/Server</a>
  *
@@ -29,6 +32,8 @@
 
     /**
      * reconnect.
+     *
+     * 重连
      */
     void reconnect() throws RemotingException;
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Codec2.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Codec2.java
index 730d00eb3a..da4c25c70f 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Codec2.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Codec2.java
@@ -23,18 +23,46 @@
 
 import java.io.IOException;
 
+/**
+ * 编解码器接口
+ */
 @SPI
 public interface Codec2 {
 
+    /**
+     * 编码
+     *
+     * @param channel 通道
+     * @param buffer Buffer
+     * @param message 消息
+     * @throws IOException 当编码发生异常时
+     */
     @Adaptive({Constants.CODEC_KEY})
     void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException;
 
+    /**
+     * 解码
+     *
+     * @param channel 通道
+     * @param buffer Buffer
+     * @return 消息
+     * @throws IOException 当解码发生异常时
+     */
     @Adaptive({Constants.CODEC_KEY})
     Object decode(Channel channel, ChannelBuffer buffer) throws IOException;
 
-
+    /**
+     * 解码结果
+     */
     enum DecodeResult {
-        NEED_MORE_INPUT, SKIP_SOME_INPUT
+        /**
+         * 需要更多输入
+         */
+        NEED_MORE_INPUT,
+        /**
+         * 忽略一些输入
+         */
+        SKIP_SOME_INPUT
     }
 
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Decodeable.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Decodeable.java
index 733fe213c5..4b0552c754 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Decodeable.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Decodeable.java
@@ -17,8 +17,16 @@
 
 package com.alibaba.dubbo.remoting;
 
+/**
+ * 可解码的接口
+ */
 public interface Decodeable {
 
-    public void decode() throws Exception;
+    /**
+     * 解码
+     *
+     * @throws Exception 发生异常
+     */
+    void decode() throws Exception;
 
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Dispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Dispatcher.java
index 15b0c0039b..9932861665 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Dispatcher.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Dispatcher.java
@@ -24,6 +24,10 @@
 
 /**
  * ChannelHandlerWrapper (SPI, Singleton, ThreadSafe)
+ *
+ * 调度器接口。
+ *
+ * 不同的调度器实现,将操作转发到对应的线程池。
  */
 @SPI(AllDispatcher.NAME)
 public interface Dispatcher {
@@ -31,7 +35,7 @@
     /**
      * dispatch the message to threadpool.
      *
-     * @param handler
+     * @param handler 通道处理器
      * @param url
      * @return channel handler
      */
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Endpoint.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Endpoint.java
index f58885fed7..17739c8be6 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Endpoint.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Endpoint.java
@@ -23,6 +23,7 @@
 /**
  * Endpoint. (API/SPI, Prototype, ThreadSafe)
  *
+ * Endpoint 接口
  *
  * @see com.alibaba.dubbo.remoting.Channel
  * @see com.alibaba.dubbo.remoting.Client
@@ -40,6 +41,8 @@
     /**
      * get channel handler.
      *
+     * 获得通道处理器
+     *
      * @return channel handler
      */
     ChannelHandler getChannelHandler();
@@ -54,7 +57,7 @@
     /**
      * send message.
      *
-     * @param message
+     * @param message 消息
      * @throws RemotingException
      */
     void send(Object message) throws RemotingException;
@@ -62,7 +65,7 @@
     /**
      * send message.
      *
-     * @param message
+     * @param message 消息
      * @param sent    already sent to socket?
      */
     void send(Object message, boolean sent) throws RemotingException;
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/ExecutionException.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/ExecutionException.java
index c1c72b0c50..455adb8c8b 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/ExecutionException.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/ExecutionException.java
@@ -21,12 +21,17 @@
 /**
  * ReceiveException
  *
+ * 执行异常
+ *
  * @export
  */
 public class ExecutionException extends RemotingException {
 
     private static final long serialVersionUID = -2531085236111056860L;
 
+    /**
+     * 请求
+     */
     private final Object request;
 
     public ExecutionException(Object request, Channel channel, String message, Throwable cause) {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/RemotingException.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/RemotingException.java
index 7ab8dce8e4..f301cd5b6a 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/RemotingException.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/RemotingException.java
@@ -34,8 +34,13 @@
 
     private static final long serialVersionUID = -3160452149606778709L;
 
+    /**
+     * 本地地址
+     */
     private InetSocketAddress localAddress;
-
+    /**
+     * 远程地址
+     */
     private InetSocketAddress remoteAddress;
 
     public RemotingException(Channel channel, String msg) {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Server.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Server.java
index 8dddb536aa..fd2c22d938 100755
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Server.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Server.java
@@ -26,12 +26,15 @@
  * <p>
  * <a href="http://en.wikipedia.org/wiki/Client%E2%80%93server_model">Client/Server</a>
  *
+ * Server 接口
+ *
  * @see com.alibaba.dubbo.remoting.Transporter#bind(com.alibaba.dubbo.common.URL, ChannelHandler)
  */
 public interface Server extends Endpoint, Resetable {
 
     /**
      * is bound.
+     * 是否绑定本地端口,提供服务。即,是否启动成功,可连接,接收消息等。
      *
      * @return bound
      */
@@ -39,6 +42,7 @@
 
     /**
      * get channels.
+     * 获得连接上服务器的通道们(客户端)
      *
      * @return channels
      */
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/TimeoutException.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/TimeoutException.java
index 1eafa54324..ab492dc3a6 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/TimeoutException.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/TimeoutException.java
@@ -21,15 +21,28 @@
 /**
  * TimeoutException. (API, Prototype, ThreadSafe)
  *
+ * 超时异常
+ *
  * @export
  * @see com.alibaba.dubbo.remoting.exchange.ResponseFuture#get()
  * @see com.alibaba.dubbo.remoting.exchange.ResponseFuture#get(int)
  */
 public class TimeoutException extends RemotingException {
 
+    private static final long serialVersionUID = 3122966731958222692L;
+
+    /**
+     * 客户端
+     */
     public static final int CLIENT_SIDE = 0;
+    /**
+     * 服务端
+     */
     public static final int SERVER_SIDE = 1;
-    private static final long serialVersionUID = 3122966731958222692L;
+
+    /**
+     * 阶段
+     */
     private final int phase;
 
     public TimeoutException(boolean serverSide, Channel channel, String message) {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Transporter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Transporter.java
index 308355a6d3..3076807f4f 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Transporter.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Transporter.java
@@ -29,6 +29,8 @@
  * <a href="http://en.wikipedia.org/wiki/Transport_Layer">Transport Layer</a>
  * <a href="http://en.wikipedia.org/wiki/Client%E2%80%93server_model">Client/Server</a>
  *
+ * 网络传输接口
+ *
  * @see com.alibaba.dubbo.remoting.Transporters
  */
 @SPI("netty")
@@ -37,10 +39,12 @@
     /**
      * Bind a server.
      *
+     * 绑定一个服务器
+     *
      * @param url     server url
-     * @param handler
-     * @return server
-     * @throws RemotingException
+     * @param handler 通道处理器
+     * @return server 服务器
+     * @throws RemotingException 当绑定发生异常时
      * @see com.alibaba.dubbo.remoting.Transporters#bind(URL, Receiver, ChannelHandler)
      */
     @Adaptive({Constants.SERVER_KEY, Constants.TRANSPORTER_KEY})
@@ -49,10 +53,12 @@
     /**
      * Connect to a server.
      *
-     * @param url     server url
-     * @param handler
-     * @return client
-     * @throws RemotingException
+     * 连接一个服务器,即创建一个客户端
+     *
+     * @param url     server url 服务器地址
+     * @param handler 通道处理器
+     * @return client 客户端
+     * @throws RemotingException 当连接发生异常时
      * @see com.alibaba.dubbo.remoting.Transporters#connect(URL, Receiver, ChannelListener)
      */
     @Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Transporters.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Transporters.java
index 9852255fe8..5b1856d534 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Transporters.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/Transporters.java
@@ -24,6 +24,8 @@
 
 /**
  * Transporter facade. (API, Static, ThreadSafe)
+ *
+ * Transporter 门面类,参见 Facade 设计模式。
  */
 public class Transporters {
 
@@ -47,12 +49,14 @@ public static Server bind(URL url, ChannelHandler... handlers) throws RemotingEx
         if (handlers == null || handlers.length == 0) {
             throw new IllegalArgumentException("handlers == null");
         }
+        // 创建 handler
         ChannelHandler handler;
         if (handlers.length == 1) {
             handler = handlers[0];
         } else {
             handler = new ChannelHandlerDispatcher(handlers);
         }
+        // 创建 Server 对象
         return getTransporter().bind(url, handler);
     }
 
@@ -64,6 +68,7 @@ public static Client connect(URL url, ChannelHandler... handlers) throws Remotin
         if (url == null) {
             throw new IllegalArgumentException("url == null");
         }
+        // 创建 handler
         ChannelHandler handler;
         if (handlers == null || handlers.length == 0) {
             handler = new ChannelHandlerAdapter();
@@ -72,6 +77,7 @@ public static Client connect(URL url, ChannelHandler... handlers) throws Remotin
         } else {
             handler = new ChannelHandlerDispatcher(handlers);
         }
+        // 创建 Client 对象
         return getTransporter().connect(url, handler);
     }
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/AbstractChannelBuffer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/AbstractChannelBuffer.java
index 6347c0d085..ca2413575f 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/AbstractChannelBuffer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/AbstractChannelBuffer.java
@@ -22,20 +22,34 @@
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 
+/**
+ * 通道 Buffer 抽象类
+ */
 public abstract class AbstractChannelBuffer implements ChannelBuffer {
 
+    /**
+     * 读取位置
+     */
     private int readerIndex;
-
+    /**
+     * 写入位置
+     */
     private int writerIndex;
-
+    /**
+     * 标记的读取位置
+     */
     private int markedReaderIndex;
-
+    /**
+     * 标记的写入位置
+     */
     private int markedWriterIndex;
 
+    @Override
     public int readerIndex() {
         return readerIndex;
     }
 
+    @Override
     public void readerIndex(int readerIndex) {
         if (readerIndex < 0 || readerIndex > writerIndex) {
             throw new IndexOutOfBoundsException();
@@ -43,10 +57,12 @@ public void readerIndex(int readerIndex) {
         this.readerIndex = readerIndex;
     }
 
+    @Override
     public int writerIndex() {
         return writerIndex;
     }
 
+    @Override
     public void writerIndex(int writerIndex) {
         if (writerIndex < readerIndex || writerIndex > capacity()) {
             throw new IndexOutOfBoundsException();
@@ -54,6 +70,7 @@ public void writerIndex(int writerIndex) {
         this.writerIndex = writerIndex;
     }
 
+    @Override
     public void setIndex(int readerIndex, int writerIndex) {
         if (readerIndex < 0 || readerIndex > writerIndex || writerIndex > capacity()) {
             throw new IndexOutOfBoundsException();
@@ -62,42 +79,52 @@ public void setIndex(int readerIndex, int writerIndex) {
         this.writerIndex = writerIndex;
     }
 
+    @Override
     public void clear() {
         readerIndex = writerIndex = 0;
     }
 
+    @Override
     public boolean readable() {
         return readableBytes() > 0;
     }
 
+    @Override
     public boolean writable() {
         return writableBytes() > 0;
     }
 
+    @Override
     public int readableBytes() {
         return writerIndex - readerIndex;
     }
 
+    @Override
     public int writableBytes() {
         return capacity() - writerIndex;
     }
 
+    @Override
     public void markReaderIndex() {
         markedReaderIndex = readerIndex;
     }
 
+    @Override
     public void resetReaderIndex() {
         readerIndex(markedReaderIndex);
     }
 
+    @Override
     public void markWriterIndex() {
         markedWriterIndex = writerIndex;
     }
 
+    @Override
     public void resetWriterIndex() {
         writerIndex = markedWriterIndex;
     }
 
+    @Override
     public void discardReadBytes() {
         if (readerIndex == 0) {
             return;
@@ -109,20 +136,24 @@ public void discardReadBytes() {
         readerIndex = 0;
     }
 
+    @Override
     public void ensureWritableBytes(int writableBytes) {
         if (writableBytes > writableBytes()) {
             throw new IndexOutOfBoundsException();
         }
     }
 
+    @Override
     public void getBytes(int index, byte[] dst) {
         getBytes(index, dst, 0, dst.length);
     }
 
+    @Override
     public void getBytes(int index, ChannelBuffer dst) {
         getBytes(index, dst, dst.writableBytes());
     }
 
+    @Override
     public void getBytes(int index, ChannelBuffer dst, int length) {
         if (length > dst.writableBytes()) {
             throw new IndexOutOfBoundsException();
@@ -131,14 +162,17 @@ public void getBytes(int index, ChannelBuffer dst, int length) {
         dst.writerIndex(dst.writerIndex() + length);
     }
 
+    @Override
     public void setBytes(int index, byte[] src) {
         setBytes(index, src, 0, src.length);
     }
 
+    @Override
     public void setBytes(int index, ChannelBuffer src) {
         setBytes(index, src, src.readableBytes());
     }
 
+    @Override
     public void setBytes(int index, ChannelBuffer src, int length) {
         if (length > src.readableBytes()) {
             throw new IndexOutOfBoundsException();
@@ -147,6 +181,7 @@ public void setBytes(int index, ChannelBuffer src, int length) {
         src.readerIndex(src.readerIndex() + length);
     }
 
+    @Override
     public byte readByte() {
         if (readerIndex == writerIndex) {
             throw new IndexOutOfBoundsException();
@@ -154,31 +189,38 @@ public byte readByte() {
         return getByte(readerIndex++);
     }
 
+    @Override
     public ChannelBuffer readBytes(int length) {
         checkReadableBytes(length);
         if (length == 0) {
             return ChannelBuffers.EMPTY_BUFFER;
         }
+        // 读取,生成 ChannelBuffer 对象
         ChannelBuffer buf = factory().getBuffer(length);
         buf.writeBytes(this, readerIndex, length);
+        // 设置读进度
         readerIndex += length;
         return buf;
     }
 
+    @Override
     public void readBytes(byte[] dst, int dstIndex, int length) {
         checkReadableBytes(length);
         getBytes(readerIndex, dst, dstIndex, length);
         readerIndex += length;
     }
 
+    @Override
     public void readBytes(byte[] dst) {
         readBytes(dst, 0, dst.length);
     }
 
+    @Override
     public void readBytes(ChannelBuffer dst) {
         readBytes(dst, dst.writableBytes());
     }
 
+    @Override
     public void readBytes(ChannelBuffer dst, int length) {
         if (length > dst.writableBytes()) {
             throw new IndexOutOfBoundsException();
@@ -187,12 +229,14 @@ public void readBytes(ChannelBuffer dst, int length) {
         dst.writerIndex(dst.writerIndex() + length);
     }
 
+    @Override
     public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
         checkReadableBytes(length);
         getBytes(readerIndex, dst, dstIndex, length);
         readerIndex += length;
     }
 
+    @Override
     public void readBytes(ByteBuffer dst) {
         int length = dst.remaining();
         checkReadableBytes(length);
@@ -200,12 +244,14 @@ public void readBytes(ByteBuffer dst) {
         readerIndex += length;
     }
 
+    @Override
     public void readBytes(OutputStream out, int length) throws IOException {
         checkReadableBytes(length);
         getBytes(readerIndex, out, length);
         readerIndex += length;
     }
 
+    @Override
     public void skipBytes(int length) {
         int newReaderIndex = readerIndex + length;
         if (newReaderIndex > writerIndex) {
@@ -214,23 +260,28 @@ public void skipBytes(int length) {
         readerIndex = newReaderIndex;
     }
 
+    @Override
     public void writeByte(int value) {
         setByte(writerIndex++, value);
     }
 
+    @Override
     public void writeBytes(byte[] src, int srcIndex, int length) {
         setBytes(writerIndex, src, srcIndex, length);
         writerIndex += length;
     }
 
+    @Override
     public void writeBytes(byte[] src) {
         writeBytes(src, 0, src.length);
     }
 
+    @Override
     public void writeBytes(ChannelBuffer src) {
         writeBytes(src, src.readableBytes());
     }
 
+    @Override
     public void writeBytes(ChannelBuffer src, int length) {
         if (length > src.readableBytes()) {
             throw new IndexOutOfBoundsException();
@@ -239,17 +290,20 @@ public void writeBytes(ChannelBuffer src, int length) {
         src.readerIndex(src.readerIndex() + length);
     }
 
+    @Override
     public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
         setBytes(writerIndex, src, srcIndex, length);
         writerIndex += length;
     }
 
+    @Override
     public void writeBytes(ByteBuffer src) {
         int length = src.remaining();
         setBytes(writerIndex, src);
         writerIndex += length;
     }
 
+    @Override
     public int writeBytes(InputStream in, int length) throws IOException {
         int writtenBytes = setBytes(writerIndex, in, length);
         if (writtenBytes > 0) {
@@ -258,10 +312,12 @@ public int writeBytes(InputStream in, int length) throws IOException {
         return writtenBytes;
     }
 
+    @Override
     public ChannelBuffer copy() {
         return copy(readerIndex, readableBytes());
     }
 
+    @Override
     public ByteBuffer toByteBuffer() {
         return toByteBuffer(readerIndex, readableBytes());
     }
@@ -290,4 +346,5 @@ protected void checkReadableBytes(int minimumReadableBytes) {
             throw new IndexOutOfBoundsException();
         }
     }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ByteBufferBackedChannelBuffer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ByteBufferBackedChannelBuffer.java
index 4d5e2eb2af..6258db5e65 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ByteBufferBackedChannelBuffer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ByteBufferBackedChannelBuffer.java
@@ -22,28 +22,43 @@
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 
+/**
+ * 基于 ByteBuffer 的 ChannelBuffer 实现类
+ */
 public class ByteBufferBackedChannelBuffer extends AbstractChannelBuffer {
 
+    /**
+     * buffer
+     * java.nio.ByteBuffer
+     */
     private final ByteBuffer buffer;
-
+    /**
+     * 容量
+     */
     private final int capacity;
 
     public ByteBufferBackedChannelBuffer(ByteBuffer buffer) {
         if (buffer == null) {
             throw new NullPointerException("buffer");
         }
-
+        // buffer
         this.buffer = buffer.slice();
+        // 容量
         capacity = buffer.remaining();
+        // 设置 `writerIndex`
         writerIndex(capacity);
     }
 
     public ByteBufferBackedChannelBuffer(ByteBufferBackedChannelBuffer buffer) {
+        // buffer
         this.buffer = buffer.buffer;
+        // 容量
         capacity = buffer.capacity;
+        // 设置 `writerIndex` `readerIndex`
         setIndex(buffer.readerIndex(), buffer.writerIndex());
     }
 
+    @Override
     public ChannelBufferFactory factory() {
         if (buffer.isDirect()) {
             return DirectChannelBufferFactory.getInstance();
@@ -52,12 +67,12 @@ public ChannelBufferFactory factory() {
         }
     }
 
-
+    @Override
     public int capacity() {
         return capacity;
     }
 
-
+    @Override
     public ChannelBuffer copy(int index, int length) {
         ByteBuffer src;
         try {
@@ -74,12 +89,12 @@ public ChannelBuffer copy(int index, int length) {
         return new ByteBufferBackedChannelBuffer(dst);
     }
 
-
+    @Override
     public byte getByte(int index) {
         return buffer.get(index);
     }
 
-
+    @Override
     public void getBytes(int index, byte[] dst, int dstIndex, int length) {
         ByteBuffer data = buffer.duplicate();
         try {
@@ -90,7 +105,7 @@ public void getBytes(int index, byte[] dst, int dstIndex, int length) {
         data.get(dst, dstIndex, length);
     }
 
-
+    @Override
     public void getBytes(int index, ByteBuffer dst) {
         ByteBuffer data = buffer.duplicate();
         int bytesToCopy = Math.min(capacity() - index, dst.remaining());
@@ -102,7 +117,7 @@ public void getBytes(int index, ByteBuffer dst) {
         dst.put(data);
     }
 
-
+    @Override
     public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
         if (dst instanceof ByteBufferBackedChannelBuffer) {
             ByteBufferBackedChannelBuffer bbdst = (ByteBufferBackedChannelBuffer) dst;
@@ -118,6 +133,7 @@ public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
     }
 
 
+    @Override
     public void getBytes(int index, OutputStream out, int length) throws IOException {
         if (length == 0) {
             return;
@@ -135,31 +151,31 @@ public void getBytes(int index, OutputStream out, int length) throws IOException
         }
     }
 
-
+    @Override
     public boolean isDirect() {
         return buffer.isDirect();
     }
 
-
+    @Override
     public void setByte(int index, int value) {
         buffer.put(index, (byte) value);
     }
 
-
+    @Override
     public void setBytes(int index, byte[] src, int srcIndex, int length) {
         ByteBuffer data = buffer.duplicate();
         data.limit(index + length).position(index);
         data.put(src, srcIndex, length);
     }
 
-
+    @Override
     public void setBytes(int index, ByteBuffer src) {
         ByteBuffer data = buffer.duplicate();
         data.limit(index + src.remaining()).position(index);
         data.put(src);
     }
 
-
+    @Override
     public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
         if (src instanceof ByteBufferBackedChannelBuffer) {
             ByteBufferBackedChannelBuffer bbsrc = (ByteBufferBackedChannelBuffer) src;
@@ -174,7 +190,7 @@ public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
         }
     }
 
-
+    @Override
     public ByteBuffer toByteBuffer(int index, int length) {
         if (index == 0 && length == capacity()) {
             return buffer.duplicate();
@@ -184,7 +200,7 @@ public ByteBuffer toByteBuffer(int index, int length) {
         }
     }
 
-
+    @Override
     public int setBytes(int index, InputStream in, int length) throws IOException {
         int readBytes = 0;
 
@@ -224,18 +240,19 @@ public int setBytes(int index, InputStream in, int length) throws IOException {
         return readBytes;
     }
 
-
+    @Override
     public byte[] array() {
         return buffer.array();
     }
 
-
+    @Override
     public boolean hasArray() {
         return buffer.hasArray();
     }
 
-
+    @Override
     public int arrayOffset() {
         return buffer.arrayOffset();
     }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBuffer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBuffer.java
index da669cfa20..89906c2090 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBuffer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBuffer.java
@@ -199,6 +199,7 @@
  * Please refer to {@link ChannelBufferInputStream} and {@link
  * ChannelBufferOutputStream}.
  *
+ * 通道 Buffer 接口
  *
  */
 public interface ChannelBuffer extends Comparable<ChannelBuffer> {
@@ -274,7 +275,7 @@
      * method also returns {@code false} for {@code null} and an object which is
      * not an instance of {@link ChannelBuffer} type.
      */
-    public boolean equals(Object o);
+    boolean equals(Object o);
 
     /**
      * Returns the factory which creates a {@link ChannelBuffer} whose type and
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferFactory.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferFactory.java
index 85fb63445b..32b7accae0 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferFactory.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferFactory.java
@@ -18,12 +18,15 @@
 
 import java.nio.ByteBuffer;
 
+/**
+ * 通道 Buffer 工厂接口
+ */
 public interface ChannelBufferFactory {
 
     ChannelBuffer getBuffer(int capacity);
 
     ChannelBuffer getBuffer(byte[] array, int offset, int length);
 
-    ChannelBuffer getBuffer(ByteBuffer nioBuffer);
+    ChannelBuffer getBuffer(ByteBuffer nioBuffer); // java.nio.ByteBuffer
 
-}
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferInputStream.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferInputStream.java
index ca566be73f..387119dc3a 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferInputStream.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferInputStream.java
@@ -17,13 +17,21 @@
 
 package com.alibaba.dubbo.remoting.buffer;
 
-import java.io.IOException;
 import java.io.InputStream;
 
+/**
+ * 通道 Buffer 输入流
+ */
 public class ChannelBufferInputStream extends InputStream {
 
     private final ChannelBuffer buffer;
+    /**
+     * 开始位置
+     */
     private final int startIndex;
+    /**
+     * 结束位置
+     */
     private final int endIndex;
 
     public ChannelBufferInputStream(ChannelBuffer buffer) {
@@ -52,7 +60,7 @@ public int readBytes() {
     }
 
     @Override
-    public int available() throws IOException {
+    public int available() {
         return endIndex - buffer.readerIndex();
     }
 
@@ -67,7 +75,7 @@ public boolean markSupported() {
     }
 
     @Override
-    public int read() throws IOException {
+    public int read() {
         if (!buffer.readable()) {
             return -1;
         }
@@ -75,7 +83,7 @@ public int read() throws IOException {
     }
 
     @Override
-    public int read(byte[] b, int off, int len) throws IOException {
+    public int read(byte[] b, int off, int len) {
         int available = available();
         if (available == 0) {
             return -1;
@@ -87,12 +95,12 @@ public int read(byte[] b, int off, int len) throws IOException {
     }
 
     @Override
-    public void reset() throws IOException {
+    public void reset() {
         buffer.resetReaderIndex();
     }
 
     @Override
-    public long skip(long n) throws IOException {
+    public long skip(long n) {
         if (n > Integer.MAX_VALUE) {
             return skipBytes(Integer.MAX_VALUE);
         } else {
@@ -100,7 +108,7 @@ public long skip(long n) throws IOException {
         }
     }
 
-    private int skipBytes(int n) throws IOException {
+    private int skipBytes(int n) {
         int nBytes = Math.min(available(), n);
         buffer.skipBytes(nBytes);
         return nBytes;
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferOutputStream.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferOutputStream.java
index 60f492a71a..37ef96daad 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferOutputStream.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBufferOutputStream.java
@@ -17,12 +17,17 @@
 
 package com.alibaba.dubbo.remoting.buffer;
 
-import java.io.IOException;
 import java.io.OutputStream;
 
+/**
+ * 通道 Buffer 输出流
+ */
 public class ChannelBufferOutputStream extends OutputStream {
 
     private final ChannelBuffer buffer;
+    /**
+     * 开始位置
+     */
     private final int startIndex;
 
     public ChannelBufferOutputStream(ChannelBuffer buffer) {
@@ -38,25 +43,25 @@ public int writtenBytes() {
     }
 
     @Override
-    public void write(byte[] b, int off, int len) throws IOException {
+    public void write(byte[] b, int off, int len) {
         if (len == 0) {
             return;
         }
-
         buffer.writeBytes(b, off, len);
     }
 
     @Override
-    public void write(byte[] b) throws IOException {
+    public void write(byte[] b) {
         buffer.writeBytes(b);
     }
 
     @Override
-    public void write(int b) throws IOException {
+    public void write(int b) {
         buffer.writeByte((byte) b);
     }
 
     public ChannelBuffer buffer() {
         return buffer;
     }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBuffers.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBuffers.java
index 4aee619445..94efdd2376 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBuffers.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/ChannelBuffers.java
@@ -19,6 +19,9 @@
 
 import java.nio.ByteBuffer;
 
+/**
+ * Buffer 工具类
+ */
 public final class ChannelBuffers {
 
     public static final ChannelBuffer EMPTY_BUFFER = new HeapChannelBuffer(0);
@@ -26,19 +29,23 @@
     private ChannelBuffers() {
     }
 
+    // DynamicChannelBuffer ,实际是 HeapChannelBuffer
     public static ChannelBuffer dynamicBuffer() {
         return dynamicBuffer(256);
     }
 
+    // DynamicChannelBuffer ,实际是 HeapChannelBuffer
     public static ChannelBuffer dynamicBuffer(int capacity) {
         return new DynamicChannelBuffer(capacity);
     }
 
+    // DynamicChannelBuffer ,实际是 HeapChannelBuffer
     public static ChannelBuffer dynamicBuffer(int capacity,
                                               ChannelBufferFactory factory) {
         return new DynamicChannelBuffer(capacity, factory);
     }
 
+    // HeapChannelBuffer
     public static ChannelBuffer buffer(int capacity) {
         if (capacity < 0) {
             throw new IllegalArgumentException("capacity can not be negative");
@@ -49,6 +56,7 @@ public static ChannelBuffer buffer(int capacity) {
         return new HeapChannelBuffer(capacity);
     }
 
+    // HeapChannelBuffer
     public static ChannelBuffer wrappedBuffer(byte[] array, int offset, int length) {
         if (array == null) {
             throw new NullPointerException("array == null");
@@ -58,6 +66,7 @@ public static ChannelBuffer wrappedBuffer(byte[] array, int offset, int length)
         return wrappedBuffer(dest);
     }
 
+    // HeapChannelBuffer
     public static ChannelBuffer wrappedBuffer(byte[] array) {
         if (array == null) {
             throw new NullPointerException("array == null");
@@ -68,6 +77,7 @@ public static ChannelBuffer wrappedBuffer(byte[] array) {
         return new HeapChannelBuffer(array);
     }
 
+    // HeapChannelBuffer || ByteBufferBackedChannelBuffer
     public static ChannelBuffer wrappedBuffer(ByteBuffer buffer) {
         if (!buffer.hasRemaining()) {
             return EMPTY_BUFFER;
@@ -79,6 +89,7 @@ public static ChannelBuffer wrappedBuffer(ByteBuffer buffer) {
         }
     }
 
+    // ByteBufferBackedChannelBuffer
     public static ChannelBuffer directBuffer(int capacity) {
         if (capacity == 0) {
             return EMPTY_BUFFER;
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/DirectChannelBufferFactory.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/DirectChannelBufferFactory.java
index 18a646ecb3..7dddc5e3e1 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/DirectChannelBufferFactory.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/DirectChannelBufferFactory.java
@@ -19,6 +19,9 @@
 
 import java.nio.ByteBuffer;
 
+/**
+ * DirectChannelBuffer 工厂
+ */
 public class DirectChannelBufferFactory implements ChannelBufferFactory {
 
     private static final DirectChannelBufferFactory INSTANCE = new DirectChannelBufferFactory();
@@ -55,21 +58,32 @@ public ChannelBuffer getBuffer(byte[] array, int offset, int length) {
             throw new IndexOutOfBoundsException("length: " + length);
         }
 
+        // 创建 ByteBufferBackedChannelBuffer 对象
         ChannelBuffer buf = getBuffer(length);
+        // 写入数据
         buf.writeBytes(array, offset, length);
         return buf;
     }
 
     public ChannelBuffer getBuffer(ByteBuffer nioBuffer) {
+        // 直接创建 ByteBufferBackedChannelBuffer 对象
         if (!nioBuffer.isReadOnly() && nioBuffer.isDirect()) {
             return ChannelBuffers.wrappedBuffer(nioBuffer);
         }
 
+        // 创建 ByteBufferBackedChannelBuffer 对象
         ChannelBuffer buf = getBuffer(nioBuffer.remaining());
+        // 写入数据
         int pos = nioBuffer.position();
         buf.writeBytes(nioBuffer);
         nioBuffer.position(pos);
         return buf;
     }
 
+//    public static void main(String[] args) {
+//        ByteBuffer nioBuffer = ByteBuffer.allocateDirect(100);
+//        nioBuffer.putInt(10);
+//        System.out.println(INSTANCE.getBuffer(nioBuffer));
+//    }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/DynamicChannelBuffer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/DynamicChannelBuffer.java
index 7f9c563b7e..cad7b26747 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/DynamicChannelBuffer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/DynamicChannelBuffer.java
@@ -22,14 +22,22 @@
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 
+/**
+ * 动态的 ChannelBuffer 实现类
+ */
 public class DynamicChannelBuffer extends AbstractChannelBuffer {
 
+    /**
+     * 工厂
+     */
     private final ChannelBufferFactory factory;
-
+    /**
+     * Buffer
+     */
     private ChannelBuffer buffer;
 
     public DynamicChannelBuffer(int estimatedLength) {
-        this(estimatedLength, HeapChannelBufferFactory.getInstance());
+        this(estimatedLength, HeapChannelBufferFactory.getInstance()); // 默认 HeapChannelBufferFactory
     }
 
     public DynamicChannelBuffer(int estimatedLength, ChannelBufferFactory factory) {
@@ -39,7 +47,9 @@ public DynamicChannelBuffer(int estimatedLength, ChannelBufferFactory factory) {
         if (factory == null) {
             throw new NullPointerException("factory");
         }
+        // 设置 `factory`
         this.factory = factory;
+        // 创建 `buffer`
         buffer = factory.getBuffer(estimatedLength);
     }
 
@@ -65,12 +75,12 @@ public void ensureWritableBytes(int minWritableBytes) {
         buffer = newBuffer;
     }
 
-
+    @Override
     public int capacity() {
         return buffer.capacity();
     }
 
-
+    @Override
     public ChannelBuffer copy(int index, int length) {
         DynamicChannelBuffer copiedBuffer = new DynamicChannelBuffer(Math.max(length, 64), factory());
         copiedBuffer.buffer = buffer.copy(index, length);
@@ -78,67 +88,67 @@ public ChannelBuffer copy(int index, int length) {
         return copiedBuffer;
     }
 
-
+    @Override
     public ChannelBufferFactory factory() {
         return factory;
     }
 
-
+    @Override
     public byte getByte(int index) {
         return buffer.getByte(index);
     }
 
-
+    @Override
     public void getBytes(int index, byte[] dst, int dstIndex, int length) {
         buffer.getBytes(index, dst, dstIndex, length);
     }
 
-
+    @Override
     public void getBytes(int index, ByteBuffer dst) {
         buffer.getBytes(index, dst);
     }
 
-
+    @Override
     public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
         buffer.getBytes(index, dst, dstIndex, length);
     }
 
-
+    @Override
     public void getBytes(int index, OutputStream dst, int length) throws IOException {
         buffer.getBytes(index, dst, length);
     }
 
-
+    @Override
     public boolean isDirect() {
         return buffer.isDirect();
     }
 
-
+    @Override
     public void setByte(int index, int value) {
         buffer.setByte(index, value);
     }
 
-
+    @Override
     public void setBytes(int index, byte[] src, int srcIndex, int length) {
         buffer.setBytes(index, src, srcIndex, length);
     }
 
-
+    @Override
     public void setBytes(int index, ByteBuffer src) {
         buffer.setBytes(index, src);
     }
 
-
+    @Override
     public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
         buffer.setBytes(index, src, srcIndex, length);
     }
 
-
+    @Override
     public int setBytes(int index, InputStream src, int length) throws IOException {
         return buffer.setBytes(index, src, length);
     }
 
-
+    @Override
     public ByteBuffer toByteBuffer(int index, int length) {
         return buffer.toByteBuffer(index, length);
     }
@@ -173,17 +183,17 @@ public int writeBytes(InputStream in, int length) throws IOException {
         return super.writeBytes(in, length);
     }
 
-
+    @Override
     public byte[] array() {
         return buffer.array();
     }
 
-
+    @Override
     public boolean hasArray() {
         return buffer.hasArray();
     }
 
-
+    @Override
     public int arrayOffset() {
         return buffer.arrayOffset();
     }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/HeapChannelBuffer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/HeapChannelBuffer.java
index e61a7d0534..05eefda943 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/HeapChannelBuffer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/HeapChannelBuffer.java
@@ -25,10 +25,14 @@
 import java.nio.channels.GatheringByteChannel;
 import java.nio.channels.ScatteringByteChannel;
 
+/**
+ * 基于字节数组的 Buffer 实现类
+ */
 public class HeapChannelBuffer extends AbstractChannelBuffer {
 
     /**
      * The underlying heap byte array that this buffer is wrapping.
+     * 字节数组
      */
     protected final byte[] array;
 
@@ -65,30 +69,42 @@ protected HeapChannelBuffer(byte[] array, int readerIndex, int writerIndex) {
         setIndex(readerIndex, writerIndex);
     }
 
+    @Override
+    public ChannelBufferFactory factory() {
+        return HeapChannelBufferFactory.getInstance();
+    }
+
+    @Override
     public boolean isDirect() {
         return false;
     }
 
+    @Override
     public int capacity() {
         return array.length;
     }
 
+    @Override
     public boolean hasArray() {
         return true;
     }
 
+    @Override
     public byte[] array() {
         return array;
     }
 
+    @Override
     public int arrayOffset() {
         return 0;
     }
 
+    @Override
     public byte getByte(int index) {
         return array[index];
     }
 
+    @Override
     public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
         if (dst instanceof HeapChannelBuffer) {
             getBytes(index, ((HeapChannelBuffer) dst).array, dstIndex, length);
@@ -97,14 +113,17 @@ public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
         }
     }
 
+    @Override
     public void getBytes(int index, byte[] dst, int dstIndex, int length) {
         System.arraycopy(array, index, dst, dstIndex, length);
     }
 
+    @Override
     public void getBytes(int index, ByteBuffer dst) {
         dst.put(array, index, Math.min(capacity() - index, dst.remaining()));
     }
 
+    @Override
     public void getBytes(int index, OutputStream out, int length)
             throws IOException {
         out.write(array, index, length);
@@ -115,26 +134,31 @@ public int getBytes(int index, GatheringByteChannel out, int length)
         return out.write(ByteBuffer.wrap(array, index, length));
     }
 
+    @Override
     public void setByte(int index, int value) {
         array[index] = (byte) value;
     }
 
+    @Override
     public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
-        if (src instanceof HeapChannelBuffer) {
+        if (src instanceof HeapChannelBuffer) { // 都是 HeapChannelBuffer ,可以直接 System#arraycopy(...)
             setBytes(index, ((HeapChannelBuffer) src).array, srcIndex, length);
         } else {
             src.getBytes(srcIndex, array, index, length);
         }
     }
 
+    @Override
     public void setBytes(int index, byte[] src, int srcIndex, int length) {
         System.arraycopy(src, srcIndex, array, index, length);
     }
 
+    @Override
     public void setBytes(int index, ByteBuffer src) {
         src.get(array, index, src.remaining());
     }
 
+    @Override
     public int setBytes(int index, InputStream in, int length) throws IOException {
         int readBytes = 0;
         do {
@@ -180,6 +204,7 @@ public int setBytes(int index, ScatteringByteChannel in, int length) throws IOEx
         return readBytes;
     }
 
+    @Override
     public ChannelBuffer copy(int index, int length) {
         if (index < 0 || length < 0 || index + length > array.length) {
             throw new IndexOutOfBoundsException();
@@ -190,10 +215,7 @@ public ChannelBuffer copy(int index, int length) {
         return new HeapChannelBuffer(copiedArray);
     }
 
-    public ChannelBufferFactory factory() {
-        return HeapChannelBufferFactory.getInstance();
-    }
-
+    @Override
     public ByteBuffer toByteBuffer(int index, int length) {
         return ByteBuffer.wrap(array, index, length);
     }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/HeapChannelBufferFactory.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/HeapChannelBufferFactory.java
index d91f2c2f15..eeb27902dc 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/HeapChannelBufferFactory.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/buffer/HeapChannelBufferFactory.java
@@ -19,6 +19,9 @@
 
 import java.nio.ByteBuffer;
 
+/**
+ * HeapChannelBuffer 工厂
+ */
 public class HeapChannelBufferFactory implements ChannelBufferFactory {
 
     private static final HeapChannelBufferFactory INSTANCE = new HeapChannelBufferFactory();
@@ -40,11 +43,14 @@ public ChannelBuffer getBuffer(byte[] array, int offset, int length) {
     }
 
     public ChannelBuffer getBuffer(ByteBuffer nioBuffer) {
+        // 传入的非 DirectByteBuffer ,直接包装出 HeapChannelBuffer 对象
         if (nioBuffer.hasArray()) {
             return ChannelBuffers.wrappedBuffer(nioBuffer);
         }
 
+        // 创建 HeapChannelBuffer 对象
         ChannelBuffer buf = getBuffer(nioBuffer.remaining());
+        // 写入数据
         int pos = nioBuffer.position();
         buf.writeBytes(nioBuffer);
         nioBuffer.position(pos);
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeChannel.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeChannel.java
index dd645c236d..b14efa39f2 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeChannel.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeChannel.java
@@ -21,31 +21,39 @@
 
 /**
  * ExchangeChannel. (API/SPI, Prototype, ThreadSafe)
+ *
+ * 信息交换通道接口
  */
 public interface ExchangeChannel extends Channel {
 
     /**
      * send request.
      *
-     * @param request
+     * 发送请求
+     *
+     * @param request 请求
      * @return response future
-     * @throws RemotingException
+     * @throws RemotingException 远程调用,发生异常
      */
     ResponseFuture request(Object request) throws RemotingException;
 
     /**
      * send request.
      *
-     * @param request
-     * @param timeout
+     * 发送请求
+     *
+     * @param request 请求
+     * @param timeout 超时时长
      * @return response future
-     * @throws RemotingException
+     * @throws RemotingException 远程调用,发生异常
      */
     ResponseFuture request(Object request, int timeout) throws RemotingException;
 
     /**
      * get message handler.
      *
+     * 获得信息交换处理器
+     *
      * @return message handler
      */
     ExchangeHandler getExchangeHandler();
@@ -53,7 +61,9 @@
     /**
      * graceful close.
      *
-     * @param timeout
+     * 优雅关闭
+     *
+     * @param timeout 超时时长
      */
     void close(int timeout);
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeClient.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeClient.java
index fd66e1144f..53641c0df0 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeClient.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeClient.java
@@ -21,8 +21,7 @@
 /**
  * ExchangeClient. (API/SPI, Prototype, ThreadSafe)
  *
- *
+ * 信息交换客户端接口
  */
 public interface ExchangeClient extends Client, ExchangeChannel {
-
 }
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeHandler.java
index 76dcdc584b..ba5d2f638c 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeHandler.java
@@ -22,16 +22,20 @@
 
 /**
  * ExchangeHandler. (API, Prototype, ThreadSafe)
+ *
+ * 信息交换处理器接口
  */
 public interface ExchangeHandler extends ChannelHandler, TelnetHandler {
 
     /**
      * reply.
      *
-     * @param channel
-     * @param request
-     * @return response
-     * @throws RemotingException
+     * 回复请求结果
+     *
+     * @param channel 通道
+     * @param request 请求
+     * @return response 请求结果
+     * @throws RemotingException 当发生异常
      */
     Object reply(ExchangeChannel channel, Object request) throws RemotingException;
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeServer.java
index 89cee7ff7b..340993aba7 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeServer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ExchangeServer.java
@@ -23,21 +23,27 @@
 
 /**
  * ExchangeServer. (API/SPI, Prototype, ThreadSafe)
+ *
+ * 信息交换服务器接口
  */
 public interface ExchangeServer extends Server {
 
     /**
      * get channels.
      *
-     * @return channels
+     * 获得通道数组
+     *
+     * @return channels 通道数组
      */
     Collection<ExchangeChannel> getExchangeChannels();
 
     /**
      * get channel.
      *
-     * @param remoteAddress
-     * @return channel
+     * 获得指定通道
+     *
+     * @param remoteAddress 远程地址
+     * @return channel 通道
      */
     ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress);
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Exchanger.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Exchanger.java
index 53588b54f1..e7d002eb00 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Exchanger.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Exchanger.java
@@ -28,6 +28,8 @@
  * <p>
  * <a href="http://en.wikipedia.org/wiki/Message_Exchange_Pattern">Message Exchange Pattern</a>
  * <a href="http://en.wikipedia.org/wiki/Request-response">Request-Response</a>
+ *
+ * 数据交换者接口
  */
 @SPI(HeaderExchanger.NAME)
 public interface Exchanger {
@@ -35,9 +37,11 @@
     /**
      * bind.
      *
-     * @param url
-     * @param handler
-     * @return message server
+     * 绑定一个服务器
+     *
+     * @param url server url
+     * @param handler 数据交换处理器
+     * @return message server 服务器
      */
     @Adaptive({Constants.EXCHANGER_KEY})
     ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException;
@@ -45,9 +49,11 @@
     /**
      * connect.
      *
-     * @param url
-     * @param handler
-     * @return message channel
+     * 连接一个服务器,即创建一个客户端
+     *
+     * @param url server url 服务器地址
+     * @param handler 数据交换处理器
+     * @return message channel 客户端
      */
     @Adaptive({Constants.EXCHANGER_KEY})
     ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException;
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Exchangers.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Exchangers.java
index 626e6f1166..a70e81732c 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Exchangers.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Exchangers.java
@@ -28,6 +28,8 @@
 
 /**
  * Exchanger facade. (API, Static, ThreadSafe)
+ *
+ * 数据交换者门面类,参见 Facade 设计模式。
  */
 public class Exchangers {
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Request.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Request.java
index 69573ee196..f18d0285ff 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Request.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Request.java
@@ -22,25 +22,53 @@
 
 /**
  * Request.
+ *
+ * 请求
  */
 public class Request {
 
+    /**
+     * 事件 - 心跳
+     */
     public static final String HEARTBEAT_EVENT = null;
-
+    /**
+     * 事件 - 只读
+     */
     public static final String READONLY_EVENT = "R";
 
+    /**
+     * 请求编号自增序列
+     */
     private static final AtomicLong INVOKE_ID = new AtomicLong(0);
 
+    /**
+     * 请求编号
+     */
     private final long mId;
-
+    /**
+     * Dubbo 版本
+     */
     private String mVersion;
-
+    /**
+     * 是否需要响应
+     *
+     * true-需要
+     * false-不需要
+     */
     private boolean mTwoWay = true;
-
+    /**
+     * 是否是事件。例如,心跳事件。
+     */
     private boolean mEvent = false;
-
+    /**
+     * 是否异常的请求。
+     *
+     * 在消息解析的时候,会出现。
+     */
     private boolean mBroken = false;
-
+    /**
+     * 数据
+     */
     private Object mData;
 
     public Request() {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Response.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Response.java
index 0422a06367..9f534a8f59 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Response.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/Response.java
@@ -18,11 +18,18 @@
 
 /**
  * Response
+ *
+ * 响应
  */
 public class Response {
 
+    /**
+     * 事件 - 心跳
+     */
     public static final String HEARTBEAT_EVENT = null;
-
+    /**
+     * 事件 - 只读
+     */
     public static final String READONLY_EVENT = "R";
 
     /**
@@ -75,16 +82,31 @@
      */
     public static final byte SERVER_THREADPOOL_EXHAUSTED_ERROR = 100;
 
+    /**
+     * 响应编号
+     *
+     * 一个 {@link Request#mId} 和 {@link Response#mId} 一一对应。
+     */
     private long mId = 0;
-
+    /**
+     * 版本
+     */
     private String mVersion;
-
+    /**
+     * 状态
+     */
     private byte mStatus = OK;
-
+    /**
+     * 是否事件
+     */
     private boolean mEvent = false;
-
+    /**
+     * 错误消息
+     */
     private String mErrorMsg;
-
+    /**
+     * 结果
+     */
     private Object mResult;
 
     public Response() {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseCallback.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseCallback.java
index 288e032de2..2aa50e14b4 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseCallback.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseCallback.java
@@ -18,20 +18,24 @@
 
 /**
  * Callback
+ *
+ * 响应回调
  */
 public interface ResponseCallback {
 
     /**
      * done.
+     * 处理执行完成
      *
-     * @param response
+     * @param response 结果
      */
     void done(Object response);
 
     /**
      * caught exception.
+     * 处理发生异常
      *
-     * @param exception
+     * @param exception 异常
      */
     void caught(Throwable exception);
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseFuture.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseFuture.java
index dae54d67af..c256dafe1b 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseFuture.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/ResponseFuture.java
@@ -21,6 +21,8 @@
 /**
  * Future. (API/SPI, Prototype, ThreadSafe)
  *
+ * 响应 Future
+ *
  * @see com.alibaba.dubbo.remoting.exchange.ExchangeChannel#request(Object)
  * @see com.alibaba.dubbo.remoting.exchange.ExchangeChannel#request(Object, int)
  */
@@ -28,6 +30,7 @@
 
     /**
      * get result.
+     * 获得值
      *
      * @return result.
      */
@@ -35,21 +38,24 @@
 
     /**
      * get result with the specified timeout.
+     * 获得值
      *
-     * @param timeoutInMillis timeout.
+     * @param timeoutInMillis timeout. 超时时长
      * @return result.
      */
     Object get(int timeoutInMillis) throws RemotingException;
 
     /**
      * set callback.
+     * 设置回调
      *
-     * @param callback
+     * @param callback 回调
      */
     void setCallback(ResponseCallback callback);
 
     /**
      * check is done.
+     * 是否完成
      *
      * @return done or not.
      */
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/codec/ExchangeCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/codec/ExchangeCodec.java
index c35da1eede..1b21ba7a83 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/codec/ExchangeCodec.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/codec/ExchangeCodec.java
@@ -42,12 +42,13 @@
 
 /**
  * ExchangeCodec.
- *
- *
- *
+ * <p>
+ * 信息交换编解码器
  */
 public class ExchangeCodec extends TelnetCodec {
 
+    private static final Logger logger = LoggerFactory.getLogger(ExchangeCodec.class);
+
     // header length.
     protected static final int HEADER_LENGTH = 16;
     // magic header.
@@ -55,42 +56,48 @@
     protected static final byte MAGIC_HIGH = Bytes.short2bytes(MAGIC)[0];
     protected static final byte MAGIC_LOW = Bytes.short2bytes(MAGIC)[1];
     // message flag.
-    protected static final byte FLAG_REQUEST = (byte) 0x80;
-    protected static final byte FLAG_TWOWAY = (byte) 0x40;
-    protected static final byte FLAG_EVENT = (byte) 0x20;
-    protected static final int SERIALIZATION_MASK = 0x1f;
-    private static final Logger logger = LoggerFactory.getLogger(ExchangeCodec.class);
+    protected static final byte FLAG_REQUEST = (byte) 0x80; // 128
+    protected static final byte FLAG_TWOWAY = (byte) 0x40; // 64
+    protected static final byte FLAG_EVENT = (byte) 0x20; // 32
+    protected static final int SERIALIZATION_MASK = 0x1f; // 31
 
     public Short getMagicCode() {
         return MAGIC;
     }
 
+    @Override
     public void encode(Channel channel, ChannelBuffer buffer, Object msg) throws IOException {
-        if (msg instanceof Request) {
+        if (msg instanceof Request) { // 请求
             encodeRequest(channel, buffer, (Request) msg);
-        } else if (msg instanceof Response) {
+        } else if (msg instanceof Response) { // 响应
             encodeResponse(channel, buffer, (Response) msg);
-        } else {
+        } else { // 提交给父类( Telnet ) 处理,目前是 Telnet 命令的结果。
             super.encode(channel, buffer, msg);
         }
     }
 
+    @Override
     public Object decode(Channel channel, ChannelBuffer buffer) throws IOException {
+        // 读取 Header 数组
         int readable = buffer.readableBytes();
         byte[] header = new byte[Math.min(readable, HEADER_LENGTH)];
         buffer.readBytes(header);
+        // 解码
         return decode(channel, buffer, readable, header);
     }
 
+    @Override
     protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byte[] header) throws IOException {
+        // 非 Dubbo 协议,目前是 Telnet 命令。
         // check magic number.
-        if (readable > 0 && header[0] != MAGIC_HIGH
-                || readable > 1 && header[1] != MAGIC_LOW) {
+        if (readable > 0 && header[0] != MAGIC_HIGH || readable > 1 && header[1] != MAGIC_LOW) {
+            // 将 buffer 完全复制到 `header` 数组中。因为,上面的 `#decode(channel, buffer)` 方法,可能未读全
             int length = header.length;
             if (header.length < readable) {
                 header = Bytes.copyOf(header, readable);
                 buffer.readBytes(header, length, readable - length);
             }
+            // 【TODO 8026 】header[i] == MAGIC_HIGH && header[i + 1] == MAGIC_LOW ?
             for (int i = 1; i < header.length - 1; i++) {
                 if (header[i] == MAGIC_HIGH && header[i + 1] == MAGIC_LOW) {
                     buffer.readerIndex(buffer.readerIndex() - header.length + i);
@@ -98,28 +105,33 @@ protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byt
                     break;
                 }
             }
+            // 提交给父类( Telnet ) 处理,目前是 Telnet 命令。
             return super.decode(channel, buffer, readable, header);
         }
+        // Header 长度不够,返回需要更多的输入
         // check length.
         if (readable < HEADER_LENGTH) {
             return DecodeResult.NEED_MORE_INPUT;
         }
 
+        // `[96 - 127]`:Body 的**长度**。通过该长度,读取 Body 。
         // get data length.
         int len = Bytes.bytes2int(header, 12);
         checkPayload(channel, len);
 
+        // 总长度不够,返回需要更多的输入
         int tt = len + HEADER_LENGTH;
         if (readable < tt) {
             return DecodeResult.NEED_MORE_INPUT;
         }
 
+        // 解析 Header + Body
         // limit input stream.
         ChannelBufferInputStream is = new ChannelBufferInputStream(buffer, len);
-
         try {
             return decodeBody(channel, is, header);
         } finally {
+            // skip 未读完的流,并打印错误日志
             if (is.available() > 0) {
                 try {
                     if (logger.isWarnEnabled()) {
@@ -133,13 +145,23 @@ protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byt
         }
     }
 
+    /**
+     * 解析,返回 Request 或 Response
+     *
+     * @param channel 通道
+     * @param is 输出
+     * @param header Header
+     * @return 结果
+     * @throws IOException 当发生 IO 异常时
+     */
     protected Object decodeBody(Channel channel, InputStream is, byte[] header) throws IOException {
         byte flag = header[2], proto = (byte) (flag & SERIALIZATION_MASK);
         Serialization s = CodecSupport.getSerialization(channel.getUrl(), proto);
         ObjectInput in = s.deserialize(channel.getUrl(), is);
+        // Response
         // get request id.
         long id = Bytes.bytes2long(header, 4);
-        if ((flag & FLAG_REQUEST) == 0) {
+        if ((flag & FLAG_REQUEST) == 0) { // Response
             // decode response.
             Response res = new Response(id);
             if ((flag & FLAG_EVENT) != 0) {
@@ -156,7 +178,7 @@ protected Object decodeBody(Channel channel, InputStream is, byte[] header) thro
                     } else if (res.isEvent()) {
                         data = decodeEventData(channel, in);
                     } else {
-                        data = decodeResponseData(channel, in, getRequestData(id));
+                        data = decodeResponseData(channel, in, getRequestData(id)); // `#getRequestData(id)` 的调用,是多余的
                     }
                     res.setResult(data);
                 } catch (Throwable t) {
@@ -167,12 +189,13 @@ protected Object decodeBody(Channel channel, InputStream is, byte[] header) thro
                 res.setErrorMessage(in.readUTF());
             }
             return res;
-        } else {
+        // Request
+        } else { // Request
             // decode request.
             Request req = new Request(id);
             req.setVersion("2.0.0");
             req.setTwoWay((flag & FLAG_TWOWAY) != 0);
-            if ((flag & FLAG_EVENT) != 0) {
+            if ((flag & FLAG_EVENT) != 0) { // 心跳事件
                 req.setEvent(Request.HEARTBEAT_EVENT);
             }
             try {
@@ -196,75 +219,113 @@ protected Object decodeBody(Channel channel, InputStream is, byte[] header) thro
 
     protected Object getRequestData(long id) {
         DefaultFuture future = DefaultFuture.getFuture(id);
-        if (future == null)
+        if (future == null) {
             return null;
+        }
         Request req = future.getRequest();
-        if (req == null)
+        if (req == null) {
             return null;
+        }
         return req.getData();
     }
 
+    /**
+     * 编码请求
+     *
+     * @param channel 通道
+     * @param buffer Buffer
+     * @param req 请求
+     * @throws IOException 当发生 IO 异常时
+     */
     protected void encodeRequest(Channel channel, ChannelBuffer buffer, Request req) throws IOException {
         Serialization serialization = getSerialization(channel);
+        // `[0, 15]`:Magic Number
         // header.
         byte[] header = new byte[HEADER_LENGTH];
         // set magic number.
         Bytes.short2bytes(MAGIC, header);
 
+        // `[16, 20]`:Serialization 编号 && `[23]`:请求。
         // set request and serialization flag.
         header[2] = (byte) (FLAG_REQUEST | serialization.getContentTypeId());
 
+        // `[21]`:`event` 是否为事件。
         if (req.isTwoWay()) header[2] |= FLAG_TWOWAY;
+        // `[22]`:`twoWay` 是否需要响应。
         if (req.isEvent()) header[2] |= FLAG_EVENT;
 
+        // `[32 - 95]`:`id` 编号,Long 型。
         // set request id.
         Bytes.long2bytes(req.getId(), header, 4);
 
+        // 编码 `Request.data` 到 Body ,并写入到 Buffer
         // encode request data.
         int savedWriteIndex = buffer.writerIndex();
         buffer.writerIndex(savedWriteIndex + HEADER_LENGTH);
         ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer);
-        ObjectOutput out = serialization.serialize(channel.getUrl(), bos);
+        ObjectOutput out = serialization.serialize(channel.getUrl(), bos); // 序列化 Output
         if (req.isEvent()) {
             encodeEventData(channel, out, req.getData());
         } else {
             encodeRequestData(channel, out, req.getData());
         }
+        // 释放资源
         out.flushBuffer();
         if (out instanceof Cleanable) {
             ((Cleanable) out).cleanup();
         }
         bos.flush();
         bos.close();
+        // 检查 Body 长度,是否超过消息上限。
         int len = bos.writtenBytes();
         checkPayload(channel, len);
+        // `[96 - 127]`:Body 的**长度**。
         Bytes.int2bytes(len, header, 12);
 
+        // 写入 Header 到 Buffer
         // write
         buffer.writerIndex(savedWriteIndex);
         buffer.writeBytes(header); // write header.
         buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len);
     }
 
+    /**
+     * 编码响应
+     *
+     * @param channel 通道
+     * @param buffer Buffer
+     * @param res 响应
+     * @throws IOException 当发生 IO 异常时
+     */
     protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response res) throws IOException {
         int savedWriteIndex = buffer.writerIndex();
         try {
             Serialization serialization = getSerialization(channel);
+            // `[0, 15]`:Magic Number
             // header.
             byte[] header = new byte[HEADER_LENGTH];
             // set magic number.
             Bytes.short2bytes(MAGIC, header);
+
+            // `[16, 20]`:Serialization 编号 && `[23]`:响应。
             // set request and serialization flag.
             header[2] = serialization.getContentTypeId();
+
+            // `[21]`:`event` 是否为事件。
             if (res.isHeartbeat()) header[2] |= FLAG_EVENT;
+
+            // `[24 - 31]`:`status` 状态。
             // set response status.
             byte status = res.getStatus();
             header[3] = status;
+
+            // `[32 - 95]`:`id` 编号,Long 型。
             // set request id.
             Bytes.long2bytes(res.getId(), header, 4);
 
+            // 编码 `Request.data` 到 Body ,并写入到 Buffer
             buffer.writerIndex(savedWriteIndex + HEADER_LENGTH);
-            ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer);
+            ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer); // 序列化 Output
             ObjectOutput out = serialization.serialize(channel.getUrl(), bos);
             // encode response data or error message.
             if (status == Response.OK) {
@@ -273,7 +334,10 @@ protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response re
                 } else {
                     encodeResponseData(channel, out, res.getResult());
                 }
-            } else out.writeUTF(res.getErrorMessage());
+            } else {
+                out.writeUTF(res.getErrorMessage());
+            }
+            // 释放资源
             out.flushBuffer();
             if (out instanceof Cleanable) {
                 ((Cleanable) out).cleanup();
@@ -281,21 +345,27 @@ protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response re
             bos.flush();
             bos.close();
 
+            // 检查 Body 长度,是否超过消息上限。
             int len = bos.writtenBytes();
             checkPayload(channel, len);
+            // `[96 - 127]`:Body 的**长度**。
             Bytes.int2bytes(len, header, 12);
+
+            // 写入 Header 到 Buffer
             // write
             buffer.writerIndex(savedWriteIndex);
             buffer.writeBytes(header); // write header.
             buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len);
         } catch (Throwable t) {
             // clear buffer
+            // 重置写入进度,下面新的 Response 需要用到。
             buffer.writerIndex(savedWriteIndex);
             // send error message to Consumer, otherwise, Consumer will wait till timeout.
             if (!res.isEvent() && res.getStatus() != Response.BAD_RESPONSE) {
                 Response r = new Response(res.getId(), res.getVersion());
                 r.setStatus(Response.BAD_RESPONSE);
 
+                // 过长异常
                 if (t instanceof ExceedPayloadLimitException) {
                     logger.warn(t.getMessage(), t);
                     try {
@@ -305,6 +375,7 @@ protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response re
                     } catch (RemotingException e) {
                         logger.warn("Failed to send bad_response info back: " + t.getMessage() + ", cause: " + e.getMessage(), e);
                     }
+                // 其他异常
                 } else {
                     // FIXME log error message in Codec and handle in caught() of IoHanndler?
                     logger.warn("Fail to encode response: " + res + ", send bad_response info instead, cause: " + t.getMessage(), t);
@@ -318,6 +389,7 @@ protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response re
                 }
             }
 
+            // 抛出异常
             // Rethrow exception
             if (t instanceof IOException) {
                 throw (IOException) t;
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/DefaultFuture.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/DefaultFuture.java
index 9ce56ba5a0..c829ad37ba 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/DefaultFuture.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/DefaultFuture.java
@@ -38,13 +38,24 @@
 
 /**
  * DefaultFuture.
+ *
+ * 默认响应 Future 实现类
  */
 public class DefaultFuture implements ResponseFuture {
 
     private static final Logger logger = LoggerFactory.getLogger(DefaultFuture.class);
 
+    /**
+     * 通道集合
+     *
+     * key:请求编号
+     */
     private static final Map<Long, Channel> CHANNELS = new ConcurrentHashMap<Long, Channel>();
-
+    /**
+     * Future 集合
+     *
+     * key:请求编号
+     */
     private static final Map<Long, DefaultFuture> FUTURES = new ConcurrentHashMap<Long, DefaultFuture>();
 
     static {
@@ -53,16 +64,46 @@
         th.start();
     }
 
+    /**
+     * 请求编号
+     */
     // invoke id.
     private final long id;
+    /**
+     * 通道
+     */
     private final Channel channel;
+    /**
+     * 请求
+     */
     private final Request request;
+    /**
+     * 超时
+     */
     private final int timeout;
+    /**
+     * 锁
+     */
     private final Lock lock = new ReentrantLock();
+    /**
+     * 完成 Condition
+     */
     private final Condition done = lock.newCondition();
+    /**
+     * 创建开始时间
+     */
     private final long start = System.currentTimeMillis();
+    /**
+     * 发送请求时间
+     */
     private volatile long sent;
+    /**
+     * 响应
+     */
     private volatile Response response;
+    /**
+     * 回调
+     */
     private volatile ResponseCallback callback;
 
     public DefaultFuture(Channel channel, Request request, int timeout) {
@@ -79,10 +120,20 @@ public static DefaultFuture getFuture(long id) {
         return FUTURES.get(id);
     }
 
+    /**
+     * @param channel 通道
+     * @return 通道是否有未结束的请求
+     */
     public static boolean hasFuture(Channel channel) {
         return CHANNELS.containsValue(channel);
     }
 
+    /**
+     * 标记已发送
+     *
+     * @param channel 通道
+     * @param request 请求
+     */
     public static void sent(Channel channel, Request request) {
         DefaultFuture future = FUTURES.get(request.getId());
         if (future != null) {
@@ -90,9 +141,17 @@ public static void sent(Channel channel, Request request) {
         }
     }
 
+    /**
+     * 接收响应( Response )
+     *
+     * @param channel 通道
+     * @param response 响应
+     */
     public static void received(Channel channel, Response response) {
         try {
+            // 移除 FUTURES
             DefaultFuture future = FUTURES.remove(response.getId());
+            // 接收结果
             if (future != null) {
                 future.doReceived(response);
             } else {
@@ -102,23 +161,28 @@ public static void received(Channel channel, Response response) {
                         + (channel == null ? "" : ", channel: " + channel.getLocalAddress()
                         + " -> " + channel.getRemoteAddress()));
             }
+        // 移除 CHANNELS
         } finally {
             CHANNELS.remove(response.getId());
         }
     }
 
+    @Override
     public Object get() throws RemotingException {
         return get(timeout);
     }
 
+    @Override
     public Object get(int timeout) throws RemotingException {
         if (timeout <= 0) {
             timeout = Constants.DEFAULT_TIMEOUT;
         }
+        // 若未完成,等待
         if (!isDone()) {
             long start = System.currentTimeMillis();
             lock.lock();
             try {
+                // 等待完成或超时
                 while (!isDone()) {
                     done.await(timeout, TimeUnit.MILLISECONDS);
                     if (isDone() || System.currentTimeMillis() - start > timeout) {
@@ -130,10 +194,12 @@ public Object get(int timeout) throws RemotingException {
             } finally {
                 lock.unlock();
             }
+            // 未完成,抛出超时异常 TimeoutException
             if (!isDone()) {
                 throw new TimeoutException(sent > 0, channel, getTimeoutMessage(false));
             }
         }
+        // 返回响应
         return returnFromResponse();
     }
 
@@ -145,25 +211,32 @@ public void cancel() {
         CHANNELS.remove(id);
     }
 
+    @Override
     public boolean isDone() {
         return response != null;
     }
 
+    @Override
     public void setCallback(ResponseCallback callback) {
+        // 已完成,调用回调
         if (isDone()) {
             invokeCallback(callback);
         } else {
             boolean isdone = false;
+            // 获得锁
             lock.lock();
             try {
+                // 未完成,设置回调
                 if (!isDone()) {
                     this.callback = callback;
                 } else {
                     isdone = true;
                 }
+            // 释放锁
             } finally {
                 lock.unlock();
             }
+            // 已完成,调用回调
             if (isdone) {
                 invokeCallback(callback);
             }
@@ -175,18 +248,19 @@ private void invokeCallback(ResponseCallback c) {
         if (callbackCopy == null) {
             throw new NullPointerException("callback cannot be null.");
         }
-        c = null;
         Response res = response;
         if (res == null) {
             throw new IllegalStateException("response cannot be null. url:" + channel.getUrl());
         }
 
+        // 正常,处理结果
         if (res.getStatus() == Response.OK) {
             try {
                 callbackCopy.done(res.getResult());
             } catch (Exception e) {
                 logger.error("callback invoke error .reasult:" + res.getResult() + ",url:" + channel.getUrl(), e);
             }
+        // 超时,处理 TimeoutException 异常
         } else if (res.getStatus() == Response.CLIENT_TIMEOUT || res.getStatus() == Response.SERVER_TIMEOUT) {
             try {
                 TimeoutException te = new TimeoutException(res.getStatus() == Response.SERVER_TIMEOUT, channel, res.getErrorMessage());
@@ -194,6 +268,7 @@ private void invokeCallback(ResponseCallback c) {
             } catch (Exception e) {
                 logger.error("callback invoke error ,url:" + channel.getUrl(), e);
             }
+        // 其他,处理 RemotingException 异常
         } else {
             try {
                 RuntimeException re = new RuntimeException(res.getErrorMessage());
@@ -204,17 +279,26 @@ private void invokeCallback(ResponseCallback c) {
         }
     }
 
+    /**
+     * 返回结果
+     *
+     * @return 结果
+     * @throws RemotingException 当发生异常
+     */
     private Object returnFromResponse() throws RemotingException {
         Response res = response;
         if (res == null) {
             throw new IllegalStateException("response cannot be null");
         }
+        // 正常,返回结果
         if (res.getStatus() == Response.OK) {
             return res.getResult();
         }
+        // 超时,抛出 TimeoutException 异常
         if (res.getStatus() == Response.CLIENT_TIMEOUT || res.getStatus() == Response.SERVER_TIMEOUT) {
             throw new TimeoutException(res.getStatus() == Response.SERVER_TIMEOUT, channel, res.getErrorMessage());
         }
+        // 其他,抛出 RemotingException 异常
         throw new RemotingException(channel, res.getErrorMessage());
     }
 
@@ -242,57 +326,83 @@ private long getStartTimestamp() {
         return start;
     }
 
+    /**
+     * 标记 `sent`
+     */
     private void doSent() {
         sent = System.currentTimeMillis();
     }
 
     private void doReceived(Response res) {
+        // 锁定
         lock.lock();
         try {
+            // 设置结果
             response = res;
+            // 通知,唤醒等待
             if (done != null) {
                 done.signal();
             }
         } finally {
+            // 释放锁定
             lock.unlock();
         }
+        // 调用回调
         if (callback != null) {
             invokeCallback(callback);
         }
     }
 
+    /**
+     * 获得异常信息提示
+     *
+     * @param scan 是否 {@link RemotingInvocationTimeoutScan} 扫描触发
+     * @return 信息提示
+     */
     private String getTimeoutMessage(boolean scan) {
         long nowTimestamp = System.currentTimeMillis();
+                // 阶段
         return (sent > 0 ? "Waiting server-side response timeout" : "Sending request timeout in client-side")
+                // 触发
                 + (scan ? " by scan timer" : "") + ". start time: "
                 + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(start))) + ", end time: "
                 + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())) + ","
+                // 剩余时间
                 + (sent > 0 ? " client elapsed: " + (sent - start)
                 + " ms, server elapsed: " + (nowTimestamp - sent)
                 : " elapsed: " + (nowTimestamp - start)) + " ms, timeout: "
-                + timeout + " ms, request: " + request + ", channel: " + channel.getLocalAddress()
-                + " -> " + channel.getRemoteAddress();
+                + timeout + " ms, request: " + request + ", " +
+                // 连接的服务器
+                "channel: " + channel.getLocalAddress() + " -> " + channel.getRemoteAddress();
     }
 
+    /**
+     * 后台扫描调用超时任务
+     */
     private static class RemotingInvocationTimeoutScan implements Runnable {
 
         public void run() {
             while (true) {
                 try {
                     for (DefaultFuture future : FUTURES.values()) {
+                        // 已完成,跳过
                         if (future == null || future.isDone()) {
                             continue;
                         }
+                        // 超时
                         if (System.currentTimeMillis() - future.getStartTimestamp() > future.getTimeout()) {
+                            // 创建超时 Response
                             // create exception response.
                             Response timeoutResponse = new Response(future.getId());
                             // set timeout status.
                             timeoutResponse.setStatus(future.isSent() ? Response.SERVER_TIMEOUT : Response.CLIENT_TIMEOUT);
                             timeoutResponse.setErrorMessage(future.getTimeoutMessage(true));
+                            // 响应结果
                             // handle response.
                             DefaultFuture.received(future.getChannel(), timeoutResponse);
                         }
                     }
+                    // 30 ms
                     Thread.sleep(30);
                 } catch (Throwable e) {
                     logger.error("Exception when scan the timeout invocation of remoting.", e);
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeHandlerAdapter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeHandlerAdapter.java
index aaefa9a291..4a660cc624 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeHandlerAdapter.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeHandlerAdapter.java
@@ -23,9 +23,12 @@
 
 /**
  * ExchangeHandlerAdapter
+ *
+ * 信息交换处理器适配器抽象类
  */
 public abstract class ExchangeHandlerAdapter extends TelnetHandlerAdapter implements ExchangeHandler {
 
+    @Override
     public Object reply(ExchangeChannel channel, Object msg) throws RemotingException {
         return null;
     }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeHandlerDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeHandlerDispatcher.java
index d770969327..dd161c6a83 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeHandlerDispatcher.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeHandlerDispatcher.java
@@ -27,13 +27,22 @@
 
 /**
  * ExchangeHandlerDispatcher
+ *
+ * 信息交换处理器调度器
  */
 public class ExchangeHandlerDispatcher implements ExchangeHandler {
 
+    /**
+     * 回复者调度器
+     */
     private final ReplierDispatcher replierDispatcher;
-
+    /**
+     * 通道处理器集合
+     */
     private final ChannelHandlerDispatcher handlerDispatcher;
-
+    /**
+     * Telnet 命令处理器
+     */
     private final TelnetHandler telnetHandler;
 
     public ExchangeHandlerDispatcher() {
@@ -80,31 +89,38 @@ public ExchangeHandlerDispatcher removeChannelHandler(ChannelHandler handler) {
         return this;
     }
 
+    @Override
     @SuppressWarnings({"unchecked", "rawtypes"})
     public Object reply(ExchangeChannel channel, Object request) throws RemotingException {
-        return ((Replier) replierDispatcher).reply(channel, request);
+        return replierDispatcher.reply(channel, request);
     }
 
+    @Override
     public void connected(Channel channel) {
         handlerDispatcher.connected(channel);
     }
 
+    @Override
     public void disconnected(Channel channel) {
         handlerDispatcher.disconnected(channel);
     }
 
+    @Override
     public void sent(Channel channel, Object message) {
         handlerDispatcher.sent(channel, message);
     }
 
+    @Override
     public void received(Channel channel, Object message) {
         handlerDispatcher.received(channel, message);
     }
 
+    @Override
     public void caught(Channel channel, Throwable exception) {
         handlerDispatcher.caught(channel, exception);
     }
 
+    @Override
     public String telnet(Channel channel, String message) throws RemotingException {
         return telnetHandler.telnet(channel, message);
     }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeServerDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeServerDelegate.java
index bcb1f9eed3..d88deb173b 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeServerDelegate.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ExchangeServerDelegate.java
@@ -28,6 +28,8 @@
 
 /**
  * ExchangeServerDelegate
+ *
+ * 信息交换服务器装饰者
  */
 public class ExchangeServerDelegate implements ExchangeServer {
 
@@ -48,10 +50,12 @@ public void setServer(ExchangeServer server) {
         this.server = server;
     }
 
+    @Override
     public boolean isBound() {
         return server.isBound();
     }
 
+    @Override
     public void reset(URL url) {
         server.reset(url);
     }
@@ -61,50 +65,62 @@ public void reset(com.alibaba.dubbo.common.Parameters parameters) {
         reset(getUrl().addParameters(parameters.getParameters()));
     }
 
+    @Override
     public Collection<Channel> getChannels() {
         return server.getChannels();
     }
 
+    @Override
     public Channel getChannel(InetSocketAddress remoteAddress) {
         return server.getChannel(remoteAddress);
     }
 
+    @Override
     public URL getUrl() {
         return server.getUrl();
     }
 
+    @Override
     public ChannelHandler getChannelHandler() {
         return server.getChannelHandler();
     }
 
+    @Override
     public InetSocketAddress getLocalAddress() {
         return server.getLocalAddress();
     }
 
+    @Override
     public void send(Object message) throws RemotingException {
         server.send(message);
     }
 
+    @Override
     public void send(Object message, boolean sent) throws RemotingException {
         server.send(message, sent);
     }
 
+    @Override
     public void close() {
         server.close();
     }
 
+    @Override
     public boolean isClosed() {
         return server.isClosed();
     }
 
+    @Override
     public Collection<ExchangeChannel> getExchangeChannels() {
         return server.getExchangeChannels();
     }
 
+    @Override
     public ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress) {
         return server.getExchangeChannel(remoteAddress);
     }
 
+    @Override
     public void close(int timeout) {
         server.close(timeout);
     }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/MultiMessage.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/MultiMessage.java
index dc68b7e04b..584edf9209 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/MultiMessage.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/MultiMessage.java
@@ -26,9 +26,14 @@
 
 /**
  * @see com.alibaba.dubbo.remoting.transport.MultiMessageHandler
+ *
+ * 多消息
  */
 public final class MultiMessage implements Iterable {
 
+    /**
+     * 消息数组
+     */
     private final List messages = new ArrayList();
 
     private MultiMessage() {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/Replier.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/Replier.java
index b2b2d25fb9..a1780b4bc1 100755
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/Replier.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/Replier.java
@@ -21,16 +21,24 @@
 
 /**
  * Replier. (API, Prototype, ThreadSafe)
+ *
+ * 回复者接口
+ *
+ * 在 ExchangeHandler 中,我们看到的是,Request 对应统一的 ExchangeHandler 实现的对象。
+ * 但是在一些场景下,我们希望实现,不同的数据类型,对应不同的处理器。
+ * Replier 就是来处理这种情况的。一个数据类型,对应一个 Replier 对象。
  */
 public interface Replier<T> {
 
     /**
      * reply.
      *
-     * @param channel
-     * @param request
-     * @return response
-     * @throws RemotingException
+     * 回复请求结果
+     *
+     * @param channel 通道
+     * @param request 泛型
+     * @return response 响应
+     * @throws RemotingException 当发生异常
      */
     Object reply(ExchangeChannel channel, T request) throws RemotingException;
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ReplierDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ReplierDispatcher.java
index 9bea4ee665..31bb445652 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ReplierDispatcher.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/ReplierDispatcher.java
@@ -24,11 +24,20 @@
 
 /**
  * ReplierDispatcher
+ *
+ * 回复者调度器实现类
  */
 public class ReplierDispatcher implements Replier<Object> {
 
+    /**
+     * 默认回复者
+     */
     private final Replier<?> defaultReplier;
-
+    /**
+     * 回复者集合
+     *
+     * key:类
+     */
     private final Map<Class<?>, Replier<?>> repliers = new ConcurrentHashMap<Class<?>, Replier<?>>();
 
     public ReplierDispatcher() {
@@ -68,6 +77,7 @@ public ReplierDispatcher(Replier<?> defaultReplier, Map<Class<?>, Replier<?>> re
         throw new IllegalStateException("Replier not found, Unsupported message object: " + type);
     }
 
+    @Override
     @SuppressWarnings({"unchecked", "rawtypes"})
     public Object reply(ExchangeChannel channel, Object request) throws RemotingException {
         return ((Replier) getReplier(request.getClass())).reply(channel, request);
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/SimpleFuture.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/SimpleFuture.java
index 555c56e34b..f7cacd6b09 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/SimpleFuture.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/SimpleFuture.java
@@ -23,6 +23,7 @@
 /**
  * SimpleFuture
  */
+@Deprecated // add by 芋艿,并未使用
 public class SimpleFuture implements ResponseFuture {
 
     private final Object value;
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java
index 9654cef0c4..90a36de8a7 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java
@@ -34,15 +34,25 @@
 
 /**
  * ExchangeReceiver
+ *
+ * 基于消息头部( Header )的信息交换通道实现类
  */
 final class HeaderExchangeChannel implements ExchangeChannel {
 
     private static final Logger logger = LoggerFactory.getLogger(HeaderExchangeChannel.class);
 
+    /**
+     * 通道键
+     */
     private static final String CHANNEL_KEY = HeaderExchangeChannel.class.getName() + ".CHANNEL";
 
+    /**
+     * 通道
+     */
     private final Channel channel;
-
+    /**
+     * 是否关闭
+     */
     private volatile boolean closed = false;
 
     HeaderExchangeChannel(Channel channel) {
@@ -52,6 +62,12 @@
         this.channel = channel;
     }
 
+    /**
+     * 创建 HeaderExchangeChannel 对象
+     *
+     * @param ch 通道
+     * @return HeaderExchangeChannel 对象
+     */
     static HeaderExchangeChannel getOrAddChannel(Channel ch) {
         if (ch == null) {
             return null;
@@ -59,23 +75,30 @@ static HeaderExchangeChannel getOrAddChannel(Channel ch) {
         HeaderExchangeChannel ret = (HeaderExchangeChannel) ch.getAttribute(CHANNEL_KEY);
         if (ret == null) {
             ret = new HeaderExchangeChannel(ch);
-            if (ch.isConnected()) {
+            if (ch.isConnected()) { // 已连接
                 ch.setAttribute(CHANNEL_KEY, ret);
             }
         }
         return ret;
     }
 
+    /**
+     * 移除 HeaderExchangeChannel 对象
+     *
+     * @param ch 通道
+     */
     static void removeChannelIfDisconnected(Channel ch) {
-        if (ch != null && !ch.isConnected()) {
+        if (ch != null && !ch.isConnected()) { // 未连接
             ch.removeAttribute(CHANNEL_KEY);
         }
     }
 
+    @Override
     public void send(Object message) throws RemotingException {
         send(message, getUrl().getParameter(Constants.SENT_KEY, false));
     }
 
+    @Override
     public void send(Object message, boolean sent) throws RemotingException {
         if (closed) {
             throw new RemotingException(this.getLocalAddress(), null, "Failed to send message " + message + ", cause: The channel " + this + " is closed!");
@@ -93,33 +116,40 @@ public void send(Object message, boolean sent) throws RemotingException {
         }
     }
 
+    @Override
     public ResponseFuture request(Object request) throws RemotingException {
         return request(request, channel.getUrl().getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT));
     }
 
+    @Override
     public ResponseFuture request(Object request, int timeout) throws RemotingException {
         if (closed) {
             throw new RemotingException(this.getLocalAddress(), null, "Failed to send request " + request + ", cause: The channel " + this + " is closed!");
         }
-        // create request.
+        // create request. 创建请求
         Request req = new Request();
         req.setVersion("2.0.0");
-        req.setTwoWay(true);
+        req.setTwoWay(true); // 需要响应
         req.setData(request);
+        // 创建 DefaultFuture 对象
         DefaultFuture future = new DefaultFuture(channel, req, timeout);
         try {
+            // 发送请求
             channel.send(req);
-        } catch (RemotingException e) {
+        } catch (RemotingException e) { // 发生异常,取消 DefaultFuture
             future.cancel();
             throw e;
         }
+        // 返回 DefaultFuture 对象
         return future;
     }
 
+    @Override
     public boolean isClosed() {
         return closed;
     }
 
+    @Override
     public void close() {
         try {
             channel.close();
@@ -129,15 +159,16 @@ public void close() {
     }
 
     // graceful close
+    @Override
     public void close(int timeout) {
         if (closed) {
             return;
         }
         closed = true;
+        // 等待请求完成
         if (timeout > 0) {
             long start = System.currentTimeMillis();
-            while (DefaultFuture.hasFuture(channel)
-                    && System.currentTimeMillis() - start < timeout) {
+            while (DefaultFuture.hasFuture(channel) && System.currentTimeMillis() - start < timeout) {
                 try {
                     Thread.sleep(10);
                 } catch (InterruptedException e) {
@@ -145,6 +176,7 @@ public void close(int timeout) {
                 }
             }
         }
+        // 关闭通道
         close();
     }
 
@@ -153,42 +185,52 @@ public void startClose() {
         channel.startClose();
     }
 
+    @Override
     public InetSocketAddress getLocalAddress() {
         return channel.getLocalAddress();
     }
 
+    @Override
     public InetSocketAddress getRemoteAddress() {
         return channel.getRemoteAddress();
     }
 
+    @Override
     public URL getUrl() {
         return channel.getUrl();
     }
 
+    @Override
     public boolean isConnected() {
         return channel.isConnected();
     }
 
+    @Override
     public ChannelHandler getChannelHandler() {
         return channel.getChannelHandler();
     }
 
+    @Override
     public ExchangeHandler getExchangeHandler() {
         return (ExchangeHandler) channel.getChannelHandler();
     }
 
+    @Override
     public Object getAttribute(String key) {
         return channel.getAttribute(key);
     }
 
+    @Override
     public void setAttribute(String key, Object value) {
         channel.setAttribute(key, value);
     }
 
+    @Override
     public void removeAttribute(String key) {
         channel.removeAttribute(key);
     }
 
+    @Override
     public boolean hasAttribute(String key) {
         return channel.hasAttribute(key);
     }
@@ -197,7 +239,7 @@ public boolean hasAttribute(String key) {
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + ((channel == null) ? 0 : channel.hashCode());
+        result = prime * result + channel.hashCode();
         return result;
     }
 
@@ -207,10 +249,7 @@ public boolean equals(Object obj) {
         if (obj == null) return false;
         if (getClass() != obj.getClass()) return false;
         HeaderExchangeChannel other = (HeaderExchangeChannel) obj;
-        if (channel == null) {
-            if (other.channel != null) return false;
-        } else if (!channel.equals(other.channel)) return false;
-        return true;
+        return channel.equals(other.channel);
     }
 
     @Override
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java
index acb95d1fd0..45ca748009 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeClient.java
@@ -39,18 +39,38 @@
 
 /**
  * DefaultMessageClient
+ *
+ * 基于消息头部( Header )的信息交换客户端实现类
  */
 public class HeaderExchangeClient implements ExchangeClient {
 
     private static final Logger logger = LoggerFactory.getLogger(HeaderExchangeClient.class);
 
+    /**
+     * 定时器线程池
+     */
     private static final ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(2, new NamedThreadFactory("dubbo-remoting-client-heartbeat", true));
+    /**
+     * 客户端
+     */
     private final Client client;
+    /**
+     * 信息交换通道
+     */
     private final ExchangeChannel channel;
     // heartbeat timer
+    /**
+     * 心跳定时器
+     */
     private ScheduledFuture<?> heartbeatTimer;
+    /**
+     * 是否心跳
+     */
     private int heartbeat;
     // heartbeat timeout (ms), default value is 0 , won't execute a heartbeat.
+    /**
+     * 心跳间隔,单位:毫秒
+     */
     private int heartbeatTimeout;
 
     public HeaderExchangeClient(Client client, boolean needHeartbeat) {
@@ -58,62 +78,77 @@ public HeaderExchangeClient(Client client, boolean needHeartbeat) {
             throw new IllegalArgumentException("client == null");
         }
         this.client = client;
+        // 创建 HeaderExchangeChannel 对象
         this.channel = new HeaderExchangeChannel(client);
+        // 读取心跳相关配置
         String dubbo = client.getUrl().getParameter(Constants.DUBBO_VERSION_KEY);
         this.heartbeat = client.getUrl().getParameter(Constants.HEARTBEAT_KEY, dubbo != null && dubbo.startsWith("1.0.") ? Constants.DEFAULT_HEARTBEAT : 0);
         this.heartbeatTimeout = client.getUrl().getParameter(Constants.HEARTBEAT_TIMEOUT_KEY, heartbeat * 3);
-        if (heartbeatTimeout < heartbeat * 2) {
+        if (heartbeatTimeout < heartbeat * 2) { // 避免间隔太短
             throw new IllegalStateException("heartbeatTimeout < heartbeatInterval * 2");
         }
+        // 发起心跳定时器
         if (needHeartbeat) {
             startHeatbeatTimer();
         }
     }
 
+    @Override
     public ResponseFuture request(Object request) throws RemotingException {
         return channel.request(request);
     }
 
+    @Override
     public URL getUrl() {
         return channel.getUrl();
     }
 
+    @Override
     public InetSocketAddress getRemoteAddress() {
         return channel.getRemoteAddress();
     }
 
+    @Override
     public ResponseFuture request(Object request, int timeout) throws RemotingException {
         return channel.request(request, timeout);
     }
 
+    @Override
     public ChannelHandler getChannelHandler() {
         return channel.getChannelHandler();
     }
 
+    @Override
     public boolean isConnected() {
         return channel.isConnected();
     }
 
+    @Override
     public InetSocketAddress getLocalAddress() {
         return channel.getLocalAddress();
     }
 
+    @Override
     public ExchangeHandler getExchangeHandler() {
         return channel.getExchangeHandler();
     }
 
+    @Override
     public void send(Object message) throws RemotingException {
         channel.send(message);
     }
 
+    @Override
     public void send(Object message, boolean sent) throws RemotingException {
         channel.send(message, sent);
     }
 
+    @Override
     public boolean isClosed() {
         return channel.isClosed();
     }
 
+    @Override
     public void close() {
         doClose();
         channel.close();
@@ -131,6 +166,7 @@ public void startClose() {
         channel.startClose();
     }
 
+    @Override
     public void reset(URL url) {
         client.reset(url);
     }
@@ -140,28 +176,35 @@ public void reset(com.alibaba.dubbo.common.Parameters parameters) {
         reset(getUrl().addParameters(parameters.getParameters()));
     }
 
+    @Override
     public void reconnect() throws RemotingException {
         client.reconnect();
     }
 
+    @Override
     public Object getAttribute(String key) {
         return channel.getAttribute(key);
     }
 
+    @Override
     public void setAttribute(String key, Object value) {
         channel.setAttribute(key, value);
     }
 
+    @Override
     public void removeAttribute(String key) {
         channel.removeAttribute(key);
     }
 
+    @Override
     public boolean hasAttribute(String key) {
         return channel.hasAttribute(key);
     }
 
     private void startHeatbeatTimer() {
+        // 停止原有定时任务
         stopHeartbeatTimer();
+        // 发起新的定时任务
         if (heartbeat > 0) {
             heartbeatTimer = scheduled.scheduleWithFixedDelay(
                     new HeartBeatTask(new HeartBeatTask.ChannelProvider() {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java
index dedd61c787..a9090b4797 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeHandler.java
@@ -37,6 +37,8 @@
 
 /**
  * ExchangeReceiver
+ *
+ * 基于消息头部( Header )的信息交换处理器实现类
  */
 public class HeaderExchangeHandler implements ChannelHandlerDelegate {
 
@@ -55,7 +57,13 @@ public HeaderExchangeHandler(ExchangeHandler handler) {
         this.handler = handler;
     }
 
-    static void handleResponse(Channel channel, Response response) throws RemotingException {
+    /**
+     * 处理响应
+     *
+     * @param channel 通道
+     * @param response 响应
+     */
+    static void handleResponse(Channel channel, Response response) {
         if (response != null && !response.isHeartbeat()) {
             DefaultFuture.received(channel, response);
         }
@@ -69,26 +77,44 @@ private static boolean isClientSide(Channel channel) {
                         .equals(NetUtils.filterLocalHost(address.getAddress().getHostAddress()));
     }
 
-    void handlerEvent(Channel channel, Request req) throws RemotingException {
+    /**
+     * 处理事件请求
+     *
+     * @param channel 通道
+     * @param req 请求
+     */
+    void handlerEvent(Channel channel, Request req) {
+        // 客户端接收到 READONLY_EVENT 事件请求,进行记录到通道。后续,不再向该服务器,发送新的请求。
         if (req.getData() != null && req.getData().equals(Request.READONLY_EVENT)) {
             channel.setAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY, Boolean.TRUE);
         }
     }
 
-    Response handleRequest(ExchangeChannel channel, Request req) throws RemotingException {
+    /**
+     * 处理普通请求( Request)
+     *
+     * @param channel 通道
+     * @param req 请求
+     * @return 响应( Response)
+     */
+    Response handleRequest(ExchangeChannel channel, Request req) {
         Response res = new Response(req.getId(), req.getVersion());
+        // 请求无法解析,返回 BAD_REQUEST 响应
         if (req.isBroken()) {
             Object data = req.getData();
-
-            String msg;
-            if (data == null) msg = null;
-            else if (data instanceof Throwable) msg = StringUtils.toString((Throwable) data);
-            else msg = data.toString();
+            String msg; // 请求数据,转成 msg
+            if (data == null) {
+                msg = null;
+            } else if (data instanceof Throwable) {
+                msg = StringUtils.toString((Throwable) data);
+            } else {
+                msg = data.toString();
+            }
             res.setErrorMessage("Fail to decode request due to: " + msg);
             res.setStatus(Response.BAD_REQUEST);
-
             return res;
         }
+        // 使用 ExchangeHandler 处理,并返回响应
         // find handler by message class.
         Object msg = req.getData();
         try {
@@ -103,45 +129,62 @@ Response handleRequest(ExchangeChannel channel, Request req) throws RemotingExce
         return res;
     }
 
+    @Override
     public void connected(Channel channel) throws RemotingException {
+        // 设置最后的读和写时间
         channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
         channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis());
+        // 创建 ExchangeChannel 对象
         ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
         try {
+            // 提交给装饰的 `handler`,继续处理
             handler.connected(exchangeChannel);
         } finally {
+            // 移除 ExchangeChannel 对象,若已断开
             HeaderExchangeChannel.removeChannelIfDisconnected(channel);
         }
     }
 
+    @Override
     public void disconnected(Channel channel) throws RemotingException {
+        // 设置最后的读和写时间
         channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
         channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis());
+        // 创建 ExchangeChannel 对象
         ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
         try {
+            // 提交给装饰的 `handler`,继续处理
             handler.disconnected(exchangeChannel);
         } finally {
+            // 移除 ExchangeChannel 对象,若已断开
             HeaderExchangeChannel.removeChannelIfDisconnected(channel);
         }
     }
 
+    @Override
     public void sent(Channel channel, Object message) throws RemotingException {
         Throwable exception = null;
         try {
+            // 设置最后的写时间
             channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis());
+            // 创建 ExchangeChannel 对象
             ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
             try {
+                // 提交给装饰的 `handler`,继续处理
                 handler.sent(exchangeChannel, message);
             } finally {
+                // 移除 ExchangeChannel 对象,若已断开
                 HeaderExchangeChannel.removeChannelIfDisconnected(channel);
             }
         } catch (Throwable t) {
-            exception = t;
+            exception = t; // 记录异常,等下面在抛出。其实,这里可以写成 finally 的方式。
         }
+        // 若是请求,标记已发送
         if (message instanceof Request) {
             Request request = (Request) message;
             DefaultFuture.sent(channel, request);
         }
+        // 若发生异常,抛出异常
         if (exception != null) {
             if (exception instanceof RuntimeException) {
                 throw (RuntimeException) exception;
@@ -154,50 +197,65 @@ public void sent(Channel channel, Object message) throws RemotingException {
         }
     }
 
+    @Override
     public void received(Channel channel, Object message) throws RemotingException {
+        // 设置最后的读时间
         channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
+        // 创建 ExchangeChannel 对象
         ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
         try {
+            // 处理请求( Request )
             if (message instanceof Request) {
                 // handle request.
                 Request request = (Request) message;
+                // 处理事件请求
                 if (request.isEvent()) {
                     handlerEvent(channel, request);
                 } else {
+                    // 处理普通请求
                     if (request.isTwoWay()) {
                         Response response = handleRequest(exchangeChannel, request);
                         channel.send(response);
+                    // 提交给装饰的 `handler`,继续处理
                     } else {
                         handler.received(exchangeChannel, request.getData());
                     }
                 }
+            // 处理响应( Response )
             } else if (message instanceof Response) {
                 handleResponse(channel, (Response) message);
+            // 处理 String
             } else if (message instanceof String) {
+                // 客户端侧,不支持 String
                 if (isClientSide(channel)) {
                     Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl());
                     logger.error(e.getMessage(), e);
+                // 服务端侧,目前是 telnet 命令
                 } else {
                     String echo = handler.telnet(channel, (String) message);
                     if (echo != null && echo.length() > 0) {
                         channel.send(echo);
                     }
                 }
+                // 提交给装饰的 `handler`,继续处理
             } else {
                 handler.received(exchangeChannel, message);
             }
         } finally {
+            // 移除 ExchangeChannel 对象,若已断开
             HeaderExchangeChannel.removeChannelIfDisconnected(channel);
         }
     }
 
+    @Override
     public void caught(Channel channel, Throwable exception) throws RemotingException {
+        // 当发生 ExecutionException 异常,返回异常响应( Response )
         if (exception instanceof ExecutionException) {
             ExecutionException e = (ExecutionException) exception;
             Object msg = e.getRequest();
             if (msg instanceof Request) {
                 Request req = (Request) msg;
-                if (req.isTwoWay() && !req.isHeartbeat()) {
+                if (req.isTwoWay() && !req.isHeartbeat()) { // 需要响应,并且非心跳时间
                     Response res = new Response(req.getId(), req.getVersion());
                     res.setStatus(Response.SERVER_ERROR);
                     res.setErrorMessage(StringUtils.toString(e));
@@ -206,14 +264,18 @@ public void caught(Channel channel, Throwable exception) throws RemotingExceptio
                 }
             }
         }
+        // 创建 ExchangeChannel 对象
         ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
         try {
+            // 提交给装饰的 `handler`,继续处理
             handler.caught(exchangeChannel, exception);
         } finally {
+            // 移除 ExchangeChannel 对象,若已断开
             HeaderExchangeChannel.removeChannelIfDisconnected(channel);
         }
     }
 
+    @Override
     public ChannelHandler getHandler() {
         if (handler instanceof ChannelHandlerDelegate) {
             return ((ChannelHandlerDelegate) handler).getHandler();
@@ -221,4 +283,5 @@ public ChannelHandler getHandler() {
             return handler;
         }
     }
+
 }
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java
index 6d77a1822a..0f585f7a15 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java
@@ -43,33 +43,52 @@
 
 /**
  * ExchangeServerImpl
+ *
+ * 基于消息头部( Header )的信息交换服务器实现类
  */
 public class HeaderExchangeServer implements ExchangeServer {
 
     protected final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private final ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1,
-            new NamedThreadFactory(
-                    "dubbo-remoting-server-heartbeat",
-                    true));
+    /**
+     * 定时器线程池
+     */
+    private final ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1, new NamedThreadFactory("dubbo-remoting-server-heartbeat", true));
+    /**
+     * 服务器
+     */
     private final Server server;
     // heartbeat timer
+    /**
+     * 心跳定时器
+     */
     private ScheduledFuture<?> heatbeatTimer;
+    /**
+     * 是否心跳
+     */
     // heartbeat timeout (ms), default value is 0 , won't execute a heartbeat.
     private int heartbeat;
+    /**
+     * 心跳间隔,单位:毫秒
+     */
     private int heartbeatTimeout;
+    /**
+     * 是否关闭
+     */
     private AtomicBoolean closed = new AtomicBoolean(false);
 
     public HeaderExchangeServer(Server server) {
         if (server == null) {
             throw new IllegalArgumentException("server == null");
         }
+        // 读取心跳相关配置
         this.server = server;
         this.heartbeat = server.getUrl().getParameter(Constants.HEARTBEAT_KEY, 0);
         this.heartbeatTimeout = server.getUrl().getParameter(Constants.HEARTBEAT_TIMEOUT_KEY, heartbeat * 3);
         if (heartbeatTimeout < heartbeat * 2) {
             throw new IllegalStateException("heartbeatTimeout < heartbeatInterval * 2");
         }
+        // 发起心跳定时器
         startHeatbeatTimer();
     }
 
@@ -77,6 +96,7 @@ public Server getServer() {
         return server;
     }
 
+    @Override
     public boolean isClosed() {
         return server.isClosed();
     }
@@ -91,21 +111,25 @@ private boolean isRunning() {
         return false;
     }
 
+    @Override
     public void close() {
         doClose();
         server.close();
     }
 
+    @Override
     public void close(final int timeout) {
+        // 关闭
         startClose();
         if (timeout > 0) {
             final long max = (long) timeout;
             final long start = System.currentTimeMillis();
+            // 发送 READONLY 事件给所有 Client ,表示 Server 不可读了。
             if (getUrl().getParameter(Constants.CHANNEL_SEND_READONLYEVENT_KEY, true)) {
                 sendChannelReadOnlyEvent();
             }
-            while (HeaderExchangeServer.this.isRunning()
-                    && System.currentTimeMillis() - start < max) {
+            // 等待请求完成
+            while (HeaderExchangeServer.this.isRunning() && System.currentTimeMillis() - start < max) {
                 try {
                     Thread.sleep(10);
                 } catch (InterruptedException e) {
@@ -113,7 +137,9 @@ public void close(final int timeout) {
                 }
             }
         }
+        // 关闭心跳定时器
         doClose();
+        // 关闭服务器
         server.close(timeout);
     }
 
@@ -122,12 +148,17 @@ public void startClose() {
         server.startClose();
     }
 
+    /**
+     * 广播客户端,READONLY_EVENT 事件
+     */
     private void sendChannelReadOnlyEvent() {
+        // 创建 READONLY_EVENT 请求
         Request request = new Request();
         request.setEvent(Request.READONLY_EVENT);
-        request.setTwoWay(false);
+        request.setTwoWay(false); // 无需响应
         request.setVersion(Version.getVersion());
 
+        // 发送给所有 Client
         Collection<Channel> channels = getChannels();
         for (Channel channel : channels) {
             try {
@@ -151,6 +182,7 @@ private void doClose() {
         }
     }
 
+    @Override
     public Collection<ExchangeChannel> getExchangeChannels() {
         Collection<ExchangeChannel> exchangeChannels = new ArrayList<ExchangeChannel>();
         Collection<Channel> channels = server.getChannels();
@@ -162,37 +194,46 @@ private void doClose() {
         return exchangeChannels;
     }
 
+    @Override
     public ExchangeChannel getExchangeChannel(InetSocketAddress remoteAddress) {
         Channel channel = server.getChannel(remoteAddress);
         return HeaderExchangeChannel.getOrAddChannel(channel);
     }
 
+    @Override
     @SuppressWarnings({"unchecked", "rawtypes"})
     public Collection<Channel> getChannels() {
         return (Collection) getExchangeChannels();
     }
 
+    @Override
     public Channel getChannel(InetSocketAddress remoteAddress) {
         return getExchangeChannel(remoteAddress);
     }
 
+    @Override
     public boolean isBound() {
         return server.isBound();
     }
 
+    @Override
     public InetSocketAddress getLocalAddress() {
         return server.getLocalAddress();
     }
 
+    @Override
     public URL getUrl() {
         return server.getUrl();
     }
 
+    @Override
     public ChannelHandler getChannelHandler() {
         return server.getChannelHandler();
     }
 
+    @Override
     public void reset(URL url) {
+        // 重置服务器
         server.reset(url);
         try {
             if (url.hasParameter(Constants.HEARTBEAT_KEY)
@@ -202,6 +243,7 @@ public void reset(URL url) {
                 if (t < h * 2) {
                     throw new IllegalStateException("heartbeatTimeout < heartbeatInterval * 2");
                 }
+                // 重置定时任务
                 if (h != heartbeat || t != heartbeatTimeout) {
                     heartbeat = h;
                     heartbeatTimeout = t;
@@ -218,6 +260,7 @@ public void reset(com.alibaba.dubbo.common.Parameters parameters) {
         reset(getUrl().addParameters(parameters.getParameters()));
     }
 
+    @Override
     public void send(Object message) throws RemotingException {
         if (closed.get()) {
             throw new RemotingException(this.getLocalAddress(), null, "Failed to send message " + message + ", cause: The server " + getLocalAddress() + " is closed!");
@@ -225,6 +268,7 @@ public void send(Object message) throws RemotingException {
         server.send(message);
     }
 
+    @Override
     public void send(Object message, boolean sent) throws RemotingException {
         if (closed.get()) {
             throw new RemotingException(this.getLocalAddress(), null, "Failed to send message " + message + ", cause: The server " + getLocalAddress() + " is closed!");
@@ -233,13 +277,14 @@ public void send(Object message, boolean sent) throws RemotingException {
     }
 
     private void startHeatbeatTimer() {
+        // 停止原有定时任务
         stopHeartbeatTimer();
+        // 发起新的定时任务
         if (heartbeat > 0) {
             heatbeatTimer = scheduled.scheduleWithFixedDelay(
                     new HeartBeatTask(new HeartBeatTask.ChannelProvider() {
                         public Collection<Channel> getChannels() {
-                            return Collections.unmodifiableCollection(
-                                    HeaderExchangeServer.this.getChannels());
+                            return Collections.unmodifiableCollection(HeaderExchangeServer.this.getChannels());
                         }
                     }, heartbeat, heartbeatTimeout),
                     heartbeat, heartbeat, TimeUnit.MILLISECONDS);
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchanger.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchanger.java
index 1c55ebe5e0..29199aa173 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchanger.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchanger.java
@@ -28,16 +28,18 @@
 /**
  * DefaultMessenger
  *
- *
+ * 基于消息头部( Header )的信息交换者实现类
  */
 public class HeaderExchanger implements Exchanger {
 
     public static final String NAME = "header";
 
+    @Override
     public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
         return new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))), true);
     }
 
+    @Override
     public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
         return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
     }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartBeatTask.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartBeatTask.java
index 2d417b2e74..63814df76e 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartBeatTask.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartBeatTask.java
@@ -25,14 +25,21 @@
 
 import java.util.Collection;
 
+/**
+ * 心跳任务
+ */
 final class HeartBeatTask implements Runnable {
 
     private static final Logger logger = LoggerFactory.getLogger(HeartBeatTask.class);
 
     private ChannelProvider channelProvider;
-
+    /**
+     * 心跳间隔,单位:毫秒
+     */
     private int heartbeat;
-
+    /**
+     * 心跳超时时间,单位:毫秒
+     */
     private int heartbeatTimeout;
 
     HeartBeatTask(ChannelProvider provider, int heartbeat, int heartbeatTimeout) {
@@ -41,6 +48,7 @@
         this.heartbeatTimeout = heartbeatTimeout;
     }
 
+    @Override
     public void run() {
         try {
             long now = System.currentTimeMillis();
@@ -49,15 +57,14 @@ public void run() {
                     continue;
                 }
                 try {
-                    Long lastRead = (Long) channel.getAttribute(
-                            HeaderExchangeHandler.KEY_READ_TIMESTAMP);
-                    Long lastWrite = (Long) channel.getAttribute(
-                            HeaderExchangeHandler.KEY_WRITE_TIMESTAMP);
+                    Long lastRead = (Long) channel.getAttribute(HeaderExchangeHandler.KEY_READ_TIMESTAMP);
+                    Long lastWrite = (Long) channel.getAttribute(HeaderExchangeHandler.KEY_WRITE_TIMESTAMP);
+                    // 最后读写的时间,任一超过心跳间隔,发送心跳
                     if ((lastRead != null && now - lastRead > heartbeat)
                             || (lastWrite != null && now - lastWrite > heartbeat)) {
                         Request req = new Request();
                         req.setVersion("2.0.0");
-                        req.setTwoWay(true);
+                        req.setTwoWay(true); // 需要响应
                         req.setEvent(Request.HEARTBEAT_EVENT);
                         channel.send(req);
                         if (logger.isDebugEnabled()) {
@@ -65,15 +72,18 @@ public void run() {
                                     + ", cause: The channel has no data-transmission exceeds a heartbeat period: " + heartbeat + "ms");
                         }
                     }
+                    // 最后读的时间,超过心跳超时时间
                     if (lastRead != null && now - lastRead > heartbeatTimeout) {
                         logger.warn("Close channel " + channel
                                 + ", because heartbeat read idle time out: " + heartbeatTimeout + "ms");
+                        // 客户端侧,重新连接服务端
                         if (channel instanceof Client) {
                             try {
                                 ((Client) channel).reconnect();
                             } catch (Exception e) {
                                 //do nothing
                             }
+                        // 服务端侧,关闭客户端连接
                         } else {
                             channel.close();
                         }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartbeatHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartbeatHandler.java
index ae88f8c386..245e987312 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartbeatHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartbeatHandler.java
@@ -27,6 +27,9 @@
 import com.alibaba.dubbo.remoting.exchange.Response;
 import com.alibaba.dubbo.remoting.transport.AbstractChannelHandlerDelegate;
 
+/**
+ * 心跳处理器,处理心跳事件
+ */
 public class HeartbeatHandler extends AbstractChannelHandlerDelegate {
 
     private static final Logger logger = LoggerFactory.getLogger(HeartbeatHandler.class);
@@ -39,25 +42,37 @@ public HeartbeatHandler(ChannelHandler handler) {
         super(handler);
     }
 
+    @Override
     public void connected(Channel channel) throws RemotingException {
+        // 设置最后的读和写时间
         setReadTimestamp(channel);
         setWriteTimestamp(channel);
+        // 提交给装饰的 `handler`,继续处理
         handler.connected(channel);
     }
 
+    @Override
     public void disconnected(Channel channel) throws RemotingException {
+        // 清除最后的读和写时间
         clearReadTimestamp(channel);
         clearWriteTimestamp(channel);
+        // 提交给装饰的 `handler`,继续处理
         handler.disconnected(channel);
     }
 
+    @Override
     public void sent(Channel channel, Object message) throws RemotingException {
+        // 设置最后的写时间
         setWriteTimestamp(channel);
+        // 提交给装饰的 `handler`,继续处理
         handler.sent(channel, message);
     }
 
+    @Override
     public void received(Channel channel, Object message) throws RemotingException {
+        // 设置最后的读时间
         setReadTimestamp(channel);
+        // 如果是心跳事件请求,返回心跳事件的响应
         if (isHeartbeatRequest(message)) {
             Request req = (Request) message;
             if (req.isTwoWay()) {
@@ -75,16 +90,14 @@ public void received(Channel channel, Object message) throws RemotingException {
             }
             return;
         }
+        // 如果是心跳事件响应,返回
         if (isHeartbeatResponse(message)) {
             if (logger.isDebugEnabled()) {
-                logger.debug(
-                        new StringBuilder(32)
-                                .append("Receive heartbeat response in thread ")
-                                .append(Thread.currentThread().getName())
-                                .toString());
+                logger.debug(new StringBuilder(32).append("Receive heartbeat response in thread ").append(Thread.currentThread().getName()).toString());
             }
             return;
         }
+        // 提交给装饰的 `handler`,继续处理
         handler.received(channel, message);
     }
 
@@ -111,4 +124,5 @@ private boolean isHeartbeatRequest(Object message) {
     private boolean isHeartbeatResponse(Object message) {
         return message instanceof Response && ((Response) message).isHeartbeat();
     }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/TelnetHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/TelnetHandler.java
index 7ce6fde2af..7cdfa8efd9 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/TelnetHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/TelnetHandler.java
@@ -22,15 +22,18 @@
 
 /**
  * TelnetHandler
+ *
+ * Telnet 命令处理器
  */
 @SPI
 public interface TelnetHandler {
 
     /**
      * telnet.
+     * 处理 telnet 命令
      *
-     * @param channel
-     * @param message
+     * @param channel 通道
+     * @param message telnet 命令
      */
     String telnet(Channel channel, String message) throws RemotingException;
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/codec/TelnetCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/codec/TelnetCodec.java
index 37fbe700a2..690c499210 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/codec/TelnetCodec.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/codec/TelnetCodec.java
@@ -35,25 +35,49 @@
 
 /**
  * TelnetCodec
+ *
+ * Telnet 命令编解码器
  */
 public class TelnetCodec extends TransportCodec {
 
     private static final Logger logger = LoggerFactory.getLogger(TelnetCodec.class);
 
+    /**
+     * 历史命令列表
+     */
     private static final String HISTORY_LIST_KEY = "telnet.history.list";
-
+    /**
+     * 历史命令位置(用户向上或向下)
+     */
     private static final String HISTORY_INDEX_KEY = "telnet.history.index";
-
+    /**
+     * 向上
+     */
     private static final byte[] UP = new byte[]{27, 91, 65};
-
+    /**
+     * 向下
+     */
     private static final byte[] DOWN = new byte[]{27, 91, 66};
 
+    /**
+     * 回车
+     */
     private static final List<?> ENTER = Arrays.asList(new Object[]{new byte[]{'\r', '\n'} /* Windows Enter */, new byte[]{'\n'} /* Linux Enter */});
 
+    /**
+     * 退出
+     */
     private static final List<?> EXIT = Arrays.asList(new Object[]{new byte[]{3} /* Windows Ctrl+C */, new byte[]{-1, -12, -1, -3, 6} /* Linux Ctrl+C */, new byte[]{-1, -19, -1, -3, 6} /* Linux Pause */});
 
+    /**
+     * 获得通道的字符集
+     *
+     * @param channel 通道
+     * @return 字符集
+     */
     private static Charset getCharset(Channel channel) {
         if (channel != null) {
+            // 从 通道属性 获得字符集
             Object attribute = channel.getAttribute(Constants.CHARSET_KEY);
             if (attribute instanceof String) {
                 try {
@@ -64,6 +88,7 @@ private static Charset getCharset(Channel channel) {
             } else if (attribute instanceof Charset) {
                 return (Charset) attribute;
             }
+            // 从 URL属性 获得字符集
             URL url = channel.getUrl();
             if (url != null) {
                 String parameter = url.getParameter(Constants.CHARSET_KEY);
@@ -76,6 +101,7 @@ private static Charset getCharset(Channel channel) {
                 }
             }
         }
+        // 使用默认字符集
         try {
             return Charset.forName(Constants.DEFAULT_CHARSET);
         } catch (Throwable t) {
@@ -84,11 +110,20 @@ private static Charset getCharset(Channel channel) {
         return Charset.defaultCharset();
     }
 
+    /**
+     * 将命令字节数组,转成具体的一条命令。
+     *
+     * @param message 命令字节数组
+     * @param charset  字符集
+     * @return telnet 命令
+     * @throws UnsupportedEncodingException 当字符集不支持
+     */
     private static String toString(byte[] message, Charset charset) throws UnsupportedEncodingException {
         byte[] copy = new byte[message.length];
         int index = 0;
         for (int i = 0; i < message.length; i++) {
             byte b = message[i];
+            // 退格,尾部减小
             if (b == '\b') { // backspace
                 if (index > 0) {
                     index--;
@@ -98,6 +133,7 @@ private static String toString(byte[] message, Charset charset) throws Unsupport
                         index--;
                     }
                 }
+            // 换码(溢出)
             } else if (b == 27) { // escape
                 if (i < message.length - 4 && message[i + 4] == 126) {
                     i = i + 4;
@@ -106,6 +142,7 @@ private static String toString(byte[] message, Charset charset) throws Unsupport
                 } else if (i < message.length - 2) {
                     i = i + 2;
                 }
+            // 握手
             } else if (b == -1 && i < message.length - 2
                     && (message[i + 1] == -3 || message[i + 1] == -5)) { // handshake
                 i = i + 2;
@@ -116,6 +153,7 @@ private static String toString(byte[] message, Charset charset) throws Unsupport
         if (index == 0) {
             return "";
         }
+        // 创建字符串
         return new String(copy, 0, index, charset.name()).trim();
     }
 
@@ -137,17 +175,21 @@ private static boolean endsWith(byte[] message, byte[] command) throws IOExcepti
     }
 
     public void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException {
+        // telnet 命令结果
         if (message instanceof String) {
-            if (isClientSide(channel)) {
+            if (isClientSide(channel)) { // 【TODO 8025】为啥 client 侧,需要多加 \r\n
                 message = message + "\r\n";
             }
+            // 写入
             byte[] msgData = ((String) message).getBytes(getCharset(channel).name());
             buffer.writeBytes(msgData);
+        // 非 telnet 命令结果。目前不会出现
         } else {
             super.encode(channel, buffer, message);
         }
     }
 
+    @Override
     public Object decode(Channel channel, ChannelBuffer buffer) throws IOException {
         int readable = buffer.readableBytes();
         byte[] message = new byte[readable];
@@ -157,16 +199,20 @@ public Object decode(Channel channel, ChannelBuffer buffer) throws IOException {
 
     @SuppressWarnings("unchecked")
     protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byte[] message) throws IOException {
+        // 【TODO 8025】为啥 client 侧,直接返回
         if (isClientSide(channel)) {
             return toString(message, getCharset(channel));
         }
+        // 检查长度
         checkPayload(channel, readable);
         if (message == null || message.length == 0) {
             return DecodeResult.NEED_MORE_INPUT;
         }
 
+        // 处理退格的情况。
         if (message[message.length - 1] == '\b') { // Windows backspace echo
             try {
+                // 32=空格 8=退格
                 boolean doublechar = message.length >= 3 && message[message.length - 3] < 0; // double byte char
                 channel.send(new String(doublechar ? new byte[]{32, 32, 8, 8} : new byte[]{32, 8}, getCharset(channel).name()));
             } catch (RemotingException e) {
@@ -175,16 +221,18 @@ protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byt
             return DecodeResult.NEED_MORE_INPUT;
         }
 
+        // 关闭指令
         for (Object command : EXIT) {
             if (isEquals(message, (byte[]) command)) {
                 if (logger.isInfoEnabled()) {
                     logger.info(new Exception("Close channel " + channel + " on exit command: " + Arrays.toString((byte[]) command)));
                 }
-                channel.close();
+                channel.close(); // 关闭通道
                 return null;
             }
         }
 
+        // 使用历史的命令
         boolean up = endsWith(message, UP);
         boolean down = endsWith(message, DOWN);
         if (up || down) {
@@ -192,48 +240,57 @@ protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byt
             if (history == null || history.isEmpty()) {
                 return DecodeResult.NEED_MORE_INPUT;
             }
+            // 获得历史命令数组的位置
             Integer index = (Integer) channel.getAttribute(HISTORY_INDEX_KEY);
             Integer old = index;
             if (index == null) {
                 index = history.size() - 1;
             } else {
-                if (up) {
+                if (up) { // 向上
                     index = index - 1;
                     if (index < 0) {
                         index = history.size() - 1;
                     }
-                } else {
+                } else { // 向下
                     index = index + 1;
                     if (index > history.size() - 1) {
                         index = 0;
                     }
                 }
             }
+            // 获得历史命令,并发送给客户端
             if (old == null || !old.equals(index)) {
+                // 设置当前位置
                 channel.setAttribute(HISTORY_INDEX_KEY, index);
+                // 获得历史命令
                 String value = history.get(index);
+                // 拼接退格,以清除客户端原有命令
                 if (old != null && old >= 0 && old < history.size()) {
                     String ov = history.get(old);
                     StringBuilder buf = new StringBuilder();
                     for (int i = 0; i < ov.length(); i++) {
-                        buf.append("\b");
+                        buf.append("\b"); // 退格
                     }
                     for (int i = 0; i < ov.length(); i++) {
                         buf.append(" ");
                     }
                     for (int i = 0; i < ov.length(); i++) {
-                        buf.append("\b");
+                        buf.append("\b"); // 退格
                     }
                     value = buf.toString() + value;
                 }
+                // 发送命令
                 try {
                     channel.send(value);
                 } catch (RemotingException e) {
                     throw new IOException(StringUtils.toString(e));
                 }
             }
+            // 返回,需要更多指令
             return DecodeResult.NEED_MORE_INPUT;
         }
+
+        // 关闭指令
         for (Object command : EXIT) {
             if (isEquals(message, (byte[]) command)) {
                 if (logger.isInfoEnabled()) {
@@ -243,6 +300,7 @@ protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byt
                 return null;
             }
         }
+        // 查找是否回车结尾。若不是,说明一条 telnet 指令没结束。
         byte[] enter = null;
         for (Object command : ENTER) {
             if (endsWith(message, (byte[]) command)) {
@@ -253,25 +311,25 @@ protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byt
         if (enter == null) {
             return DecodeResult.NEED_MORE_INPUT;
         }
+        // 移除历史命令数组的位置
         LinkedList<String> history = (LinkedList<String>) channel.getAttribute(HISTORY_LIST_KEY);
         Integer index = (Integer) channel.getAttribute(HISTORY_INDEX_KEY);
         channel.removeAttribute(HISTORY_INDEX_KEY);
+        // 将历史命令拼接
         if (history != null && !history.isEmpty() && index != null && index >= 0 && index < history.size()) {
             String value = history.get(index);
             if (value != null) {
                 byte[] b1 = value.getBytes();
-                if (message != null && message.length > 0) {
-                    byte[] b2 = new byte[b1.length + message.length];
-                    System.arraycopy(b1, 0, b2, 0, b1.length);
-                    System.arraycopy(message, 0, b2, b1.length, message.length);
-                    message = b2;
-                } else {
-                    message = b1;
-                }
+                byte[] b2 = new byte[b1.length + message.length];
+                System.arraycopy(b1, 0, b2, 0, b1.length);
+                System.arraycopy(message, 0, b2, b1.length, message.length);
+                message = b2;
             }
         }
+        // 将命令字节数组,转成具体的一条命令
         String result = toString(message, getCharset(channel));
-        if (result != null && result.trim().length() > 0) {
+        // 添加到历史
+        if (result.trim().length() > 0) {
             if (history == null) {
                 history = new LinkedList<String>();
                 channel.setAttribute(HISTORY_LIST_KEY, history);
@@ -279,8 +337,10 @@ protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byt
             if (history.isEmpty()) {
                 history.addLast(result);
             } else if (!result.equals(history.getLast())) {
+                // 添加当前命令到历史尾部
                 history.remove(result);
                 history.addLast(result);
+                // 超过上限,移除历史的头部
                 if (history.size() > 10) {
                     history.removeFirst();
                 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/support/Help.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/support/Help.java
index b22d0bce3c..de310601b6 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/support/Help.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/support/Help.java
@@ -23,17 +23,26 @@
 import java.lang.annotation.Target;
 
 /**
- * Help
+ * Help 注解
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.TYPE})
 public @interface Help {
 
+    /**
+     * 参数说明
+     */
     String parameter() default "";
 
+    /**
+     * 简要提示
+     */
     String summary();
 
+    /**
+     * 详细提示
+     */
     String detail() default "";
 
 }
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java
index 2f08b8ef54..89cca41c69 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/telnet/support/TelnetHandlerAdapter.java
@@ -23,30 +23,37 @@
 import com.alibaba.dubbo.remoting.telnet.TelnetHandler;
 import com.alibaba.dubbo.remoting.transport.ChannelHandlerAdapter;
 
+/**
+ * telnet 处理器适配器,负责接收来自 HeaderExchangeHandler 的 telnet 命令,分发给对应的 TelnetHandler 实现类,进行处理,**返回命令结果**。
+ */
 public class TelnetHandlerAdapter extends ChannelHandlerAdapter implements TelnetHandler {
 
     private final ExtensionLoader<TelnetHandler> extensionLoader = ExtensionLoader.getExtensionLoader(TelnetHandler.class);
 
+    @Override
     public String telnet(Channel channel, String message) throws RemotingException {
+        // 处理 telnet 提示键
         String prompt = channel.getUrl().getParameterAndDecoded(Constants.PROMPT_KEY, Constants.DEFAULT_PROMPT);
         boolean noprompt = message.contains("--no-prompt");
         message = message.replace("--no-prompt", "");
+        // 拆出 telnet 命令和参数
         StringBuilder buf = new StringBuilder();
         message = message.trim();
-        String command;
+        String command; // 命令
         if (message.length() > 0) {
             int i = message.indexOf(' ');
             if (i > 0) {
-                command = message.substring(0, i).trim();
-                message = message.substring(i + 1).trim();
+                command = message.substring(0, i).trim(); // 命令
+                message = message.substring(i + 1).trim(); // 参数
             } else {
-                command = message;
-                message = "";
+                command = message; // 命令
+                message = ""; // 参数
             }
         } else {
-            command = "";
+            command = ""; // 命令
         }
         if (command.length() > 0) {
+            // 查找到对应的 TelnetHandler 对象,执行命令
             if (extensionLoader.hasExtension(command)) {
                 try {
                     String result = extensionLoader.getExtension(command).telnet(channel, message);
@@ -57,17 +64,20 @@ public String telnet(Channel channel, String message) throws RemotingException {
                 } catch (Throwable t) {
                     buf.append(t.getMessage());
                 }
+            // 查找不到对应的 TelnetHandler 对象,返回报错。
             } else {
                 buf.append("Unsupported command: ");
                 buf.append(command);
             }
         }
+        // 添加 telnet 提示语
         if (buf.length() > 0) {
             buf.append("\r\n");
         }
         if (prompt != null && prompt.length() > 0 && !noprompt) {
             buf.append(prompt);
         }
+        // 返回
         return buf.toString();
     }
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractChannel.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractChannel.java
index fd22def3d3..e0d64828a5 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractChannel.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractChannel.java
@@ -23,6 +23,8 @@
 
 /**
  * AbstractChannel
+ *
+ * Channel 抽象类
  */
 public abstract class AbstractChannel extends AbstractPeer implements Channel {
 
@@ -30,6 +32,7 @@ public AbstractChannel(URL url, ChannelHandler handler) {
         super(url, handler);
     }
 
+    @Override
     public void send(Object message, boolean sent) throws RemotingException {
         if (isClosed()) {
             throw new RemotingException(this, "Failed to send message "
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractChannelHandlerDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractChannelHandlerDelegate.java
index 8f28cbd824..c5931ab385 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractChannelHandlerDelegate.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractChannelHandlerDelegate.java
@@ -21,8 +21,14 @@
 import com.alibaba.dubbo.remoting.ChannelHandler;
 import com.alibaba.dubbo.remoting.RemotingException;
 
+/**
+ * 通道处理器装饰者抽象实现类
+ */
 public abstract class AbstractChannelHandlerDelegate implements ChannelHandlerDelegate {
 
+    /**
+     * 通道处理器
+     */
     protected ChannelHandler handler;
 
     protected AbstractChannelHandlerDelegate(ChannelHandler handler) {
@@ -30,6 +36,7 @@ protected AbstractChannelHandlerDelegate(ChannelHandler handler) {
         this.handler = handler;
     }
 
+    @Override
     public ChannelHandler getHandler() {
         if (handler instanceof ChannelHandlerDelegate) {
             return ((ChannelHandlerDelegate) handler).getHandler();
@@ -37,23 +44,29 @@ public ChannelHandler getHandler() {
         return handler;
     }
 
+    @Override
     public void connected(Channel channel) throws RemotingException {
         handler.connected(channel);
     }
 
+    @Override
     public void disconnected(Channel channel) throws RemotingException {
         handler.disconnected(channel);
     }
 
+    @Override
     public void sent(Channel channel, Object message) throws RemotingException {
         handler.sent(channel, message);
     }
 
+    @Override
     public void received(Channel channel, Object message) throws RemotingException {
         handler.received(channel, message);
     }
 
+    @Override
     public void caught(Channel channel, Throwable exception) throws RemotingException {
         handler.caught(channel, exception);
     }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractClient.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractClient.java
index 44f822fd64..414c6c4e8a 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractClient.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractClient.java
@@ -45,45 +45,83 @@
 
 /**
  * AbstractClient
+ *
+ * Client 抽象类,实现了重连逻辑。
  */
 public abstract class AbstractClient extends AbstractEndpoint implements Client {
 
-    protected static final String CLIENT_THREAD_POOL_NAME = "DubboClientHandler";
     private static final Logger logger = LoggerFactory.getLogger(AbstractClient.class);
+
+    protected static final String CLIENT_THREAD_POOL_NAME = "DubboClientHandler";
+
+    @Deprecated // 因为,{@link #createExecutor()} 方法,未声明
     private static final AtomicInteger CLIENT_THREAD_POOL_ID = new AtomicInteger();
+
+    /**
+     * 重连定时任务执行器
+     */
     private static final ScheduledThreadPoolExecutor reconnectExecutorService = new ScheduledThreadPoolExecutor(2, new NamedThreadFactory("DubboClientReconnectTimer", true));
+    /**
+     * 连接锁,用于实现发起连接和断开连接互斥,避免并发。
+     */
     private final Lock connectLock = new ReentrantLock();
+    /**
+     * 发送消息时,若断开,是否重连
+     */
     private final boolean send_reconnect;
+    /**
+     * 重连次数
+     */
     private final AtomicInteger reconnect_count = new AtomicInteger(0);
+    /**
+     * 重连时,是否已经打印过错误日志。
+     */
     // Reconnection error log has been called before?
     private final AtomicBoolean reconnect_error_log_flag = new AtomicBoolean(false);
+    /**
+     * 重连 warning 的间隔.(waring多少次之后,warning一次) //for test
+     */
     // reconnect warning period. Reconnect warning interval (log warning after how many times) //for test
     private final int reconnect_warning_period;
+    /**
+     * 关闭超时时间
+     */
     private final long shutdown_timeout;
+    /**
+     * 线程池
+     *
+     * 在调用 {@link #wrapChannelHandler(URL, ChannelHandler)} 时,会调用 {@link com.alibaba.dubbo.remoting.transport.dispatcher.WrappedChannelHandler} 创建
+     */
     protected volatile ExecutorService executor;
+    /**
+     * 重连执行任务 Future
+     */
     private volatile ScheduledFuture<?> reconnectExecutorFuture = null;
+    /**
+     * 最后成功连接时间
+     */
     // the last successed connected time
     private long lastConnectedTime = System.currentTimeMillis();
 
-
     public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {
         super(url, handler);
-
+        // 从 URL 中,获得重连相关配置项
         send_reconnect = url.getParameter(Constants.SEND_RECONNECT_KEY, false);
-
         shutdown_timeout = url.getParameter(Constants.SHUTDOWN_TIMEOUT_KEY, Constants.DEFAULT_SHUTDOWN_TIMEOUT);
-
         // The default reconnection interval is 2s, 1800 means warning interval is 1 hour.
         reconnect_warning_period = url.getParameter("reconnect.waring.period", 1800);
 
+        // 初始化客户端
         try {
             doOpen();
         } catch (Throwable t) {
-            close();
+            close(); // 失败,则关闭
             throw new RemotingException(url.toInetSocketAddress(), null,
                     "Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress()
                             + " connect to the server " + getRemoteAddress() + ", cause: " + t.getMessage(), t);
         }
+
+        // 连接服务器
         try {
             // connect.
             connect();
@@ -92,40 +130,53 @@ public AbstractClient(URL url, ChannelHandler handler) throws RemotingException
             }
         } catch (RemotingException t) {
             if (url.getParameter(Constants.CHECK_KEY, true)) {
-                close();
+                close(); // 失败,则关闭
                 throw t;
             } else {
                 logger.warn("Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress()
                         + " connect to the server " + getRemoteAddress() + " (check == false, ignore and retry later!), cause: " + t.getMessage(), t);
             }
         } catch (Throwable t) {
-            close();
+            close(); // 失败,则关闭
             throw new RemotingException(url.toInetSocketAddress(), null,
                     "Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress()
                             + " connect to the server " + getRemoteAddress() + ", cause: " + t.getMessage(), t);
         }
 
-        executor = (ExecutorService) ExtensionLoader.getExtensionLoader(DataStore.class)
-                .getDefaultExtension().get(Constants.CONSUMER_SIDE, Integer.toString(url.getPort()));
-        ExtensionLoader.getExtensionLoader(DataStore.class)
-                .getDefaultExtension().remove(Constants.CONSUMER_SIDE, Integer.toString(url.getPort()));
+        // 获得线程池
+        executor = (ExecutorService) ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension()
+                .get(Constants.CONSUMER_SIDE, Integer.toString(url.getPort()));
+        ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension()
+                .remove(Constants.CONSUMER_SIDE, Integer.toString(url.getPort()));
     }
 
+    /**
+     * 包装通道处理器
+     *
+     * @param url URL
+     * @param handler 被包装的通道处理器
+     * @return 包装后的通道处理器
+     */
     protected static ChannelHandler wrapChannelHandler(URL url, ChannelHandler handler) {
+        // 设置线程名
         url = ExecutorUtil.setThreadName(url, CLIENT_THREAD_POOL_NAME);
+        // 设置使用的线程池类型
         url = url.addParameterIfAbsent(Constants.THREADPOOL_KEY, Constants.DEFAULT_CLIENT_THREADPOOL);
+        // 包装通道处理器
         return ChannelHandlers.wrap(handler, url);
     }
 
     /**
-     * @param url
+     * 从 URL 中,获得重连频率。单位:毫秒。
+     *
+     * @param url URL
      * @return 0-false
      */
     private static int getReconnectParam(URL url) {
         int reconnect;
         String param = url.getParameter(Constants.RECONNECT_KEY);
         if (param == null || param.length() == 0 || "true".equalsIgnoreCase(param)) {
-            reconnect = Constants.DEFAULT_RECONNECT_PERIOD;
+            reconnect = Constants.DEFAULT_RECONNECT_PERIOD; // 默认 2000 毫秒
         } else if ("false".equalsIgnoreCase(param)) {
             reconnect = 0;
         } else {
@@ -143,20 +194,28 @@ private static int getReconnectParam(URL url) {
 
     /**
      * init reconnect thread
+     *
+     * 初始化重连线程
      */
     private synchronized void initConnectStatusCheckCommand() {
         //reconnect=false to close reconnect
+        // 获得获得重连频率,默认开启。
         int reconnect = getReconnectParam(getUrl());
+        // 若开启重连功能,创建重连线程
         if (reconnect > 0 && (reconnectExecutorFuture == null || reconnectExecutorFuture.isCancelled())) {
+            // 创建 Runnable 对象
             Runnable connectStatusCheckCommand = new Runnable() {
                 public void run() {
                     try {
+                        // 未连接,重连
                         if (!isConnected()) {
                             connect();
+                        // 已连接,记录最后连接时间
                         } else {
                             lastConnectedTime = System.currentTimeMillis();
                         }
                     } catch (Throwable t) {
+                        // 超过一定时间未连接上,才打印异常日志。并且,仅打印一次。默认,15 分钟。
                         String errorMsg = "client reconnect to " + getUrl().getAddress() + " find error . url: " + getUrl();
                         // wait registry sync provider list
                         if (System.currentTimeMillis() - lastConnectedTime > shutdown_timeout) {
@@ -166,20 +225,28 @@ public void run() {
                                 return;
                             }
                         }
+                        // 每一定次发现未重连,才打印告警日志。默认,1800 次,1 小时。
                         if (reconnect_count.getAndIncrement() % reconnect_warning_period == 0) {
                             logger.warn(errorMsg, t);
                         }
                     }
                 }
             };
+            // 发起定时任务
             reconnectExecutorFuture = reconnectExecutorService.scheduleWithFixedDelay(connectStatusCheckCommand, reconnect, reconnect, TimeUnit.MILLISECONDS);
         }
     }
 
+    /**
+     * 关闭重连线程
+     */
     private synchronized void destroyConnectStatusCheckCommand() {
         try {
+            // 关闭重连线程
             if (reconnectExecutorFuture != null && !reconnectExecutorFuture.isDone()) {
+                // 强制取消
                 reconnectExecutorFuture.cancel(true);
+                // 清除已经取消的任务
                 reconnectExecutorService.purge();
             }
         } catch (Throwable e) {
@@ -187,6 +254,7 @@ private synchronized void destroyConnectStatusCheckCommand() {
         }
     }
 
+    // 未调用
     protected ExecutorService createExecutor() {
         return Executors.newCachedThreadPool(new NamedThreadFactory(CLIENT_THREAD_POOL_NAME + CLIENT_THREAD_POOL_ID.incrementAndGet() + "-" + getUrl().getAddress(), true));
     }
@@ -195,6 +263,7 @@ public InetSocketAddress getConnectAddress() {
         return new InetSocketAddress(NetUtils.filterLocalHost(getUrl().getHost()), getUrl().getPort());
     }
 
+    @Override
     public InetSocketAddress getRemoteAddress() {
         Channel channel = getChannel();
         if (channel == null)
@@ -202,6 +271,7 @@ public InetSocketAddress getRemoteAddress() {
         return channel.getRemoteAddress();
     }
 
+    @Override
     public InetSocketAddress getLocalAddress() {
         Channel channel = getChannel();
         if (channel == null)
@@ -209,13 +279,13 @@ public InetSocketAddress getLocalAddress() {
         return channel.getLocalAddress();
     }
 
+    @Override
     public boolean isConnected() {
         Channel channel = getChannel();
-        if (channel == null)
-            return false;
-        return channel.isConnected();
+        return channel != null && channel.isConnected();
     }
 
+    @Override
     public Object getAttribute(String key) {
         Channel channel = getChannel();
         if (channel == null)
@@ -223,6 +293,7 @@ public Object getAttribute(String key) {
         return channel.getAttribute(key);
     }
 
+    @Override
     public void setAttribute(String key, Object value) {
         Channel channel = getChannel();
         if (channel == null)
@@ -230,6 +301,7 @@ public void setAttribute(String key, Object value) {
         channel.setAttribute(key, value);
     }
 
+    @Override
     public void removeAttribute(String key) {
         Channel channel = getChannel();
         if (channel == null)
@@ -237,17 +309,19 @@ public void removeAttribute(String key) {
         channel.removeAttribute(key);
     }
 
+    @Override
     public boolean hasAttribute(String key) {
         Channel channel = getChannel();
-        if (channel == null)
-            return false;
-        return channel.hasAttribute(key);
+        return channel != null && channel.hasAttribute(key);
     }
 
+    @Override
     public void send(Object message, boolean sent) throws RemotingException {
+        // 未连接时,开启重连功能,则先发起连接
         if (send_reconnect && !isConnected()) {
             connect();
         }
+        // 发送消息
         Channel channel = getChannel();
         //TODO Can the value returned by getChannel() be null? need improvement.
         if (channel == null || !channel.isConnected()) {
@@ -257,17 +331,23 @@ public void send(Object message, boolean sent) throws RemotingException {
     }
 
     protected void connect() throws RemotingException {
+        // 获得锁
         connectLock.lock();
         try {
+            // 已连接,
             if (isConnected()) {
                 return;
             }
+            // 初始化重连线程
             initConnectStatusCheckCommand();
+            // 执行连接
             doConnect();
+            // 连接失败,抛出异常
             if (!isConnected()) {
                 throw new RemotingException(this, "Failed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
                         + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
                         + ", cause: Connect wait timeout: " + getTimeout() + "ms.");
+            // 连接成功,打印日志
             } else {
                 if (logger.isInfoEnabled()) {
                     logger.info("Successed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
@@ -275,7 +355,9 @@ protected void connect() throws RemotingException {
                             + ", channel is " + this.getChannel());
                 }
             }
+            // 设置重连次数归零
             reconnect_count.set(0);
+            // 设置未打印过错误日志
             reconnect_error_log_flag.set(false);
         } catch (RemotingException e) {
             throw e;
@@ -284,14 +366,18 @@ protected void connect() throws RemotingException {
                     + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
                     + ", cause: " + e.getMessage(), e);
         } finally {
+            // 释放锁
             connectLock.unlock();
         }
     }
 
     public void disconnect() {
+        // 获得锁
         connectLock.lock();
         try {
+            //
             destroyConnectStatusCheckCommand();
+            // 关闭连接
             try {
                 Channel channel = getChannel();
                 if (channel != null) {
@@ -300,22 +386,29 @@ public void disconnect() {
             } catch (Throwable e) {
                 logger.warn(e.getMessage(), e);
             }
+            // 执行关闭
             try {
                 doDisConnect();
             } catch (Throwable e) {
                 logger.warn(e.getMessage(), e);
             }
         } finally {
+            // 释放锁
             connectLock.unlock();
         }
     }
 
+    @Override
     public void reconnect() throws RemotingException {
+        // 断开连接
         disconnect();
+        // 发起连接
         connect();
     }
 
+    @Override
     public void close() {
+        // 关闭线程池
         try {
             if (executor != null) {
                 ExecutorUtil.shutdownNow(executor, 100);
@@ -323,16 +416,19 @@ public void close() {
         } catch (Throwable e) {
             logger.warn(e.getMessage(), e);
         }
+        // 标记关闭
         try {
             super.close();
         } catch (Throwable e) {
             logger.warn(e.getMessage(), e);
         }
+        // 断开连接
         try {
             disconnect();
         } catch (Throwable e) {
             logger.warn(e.getMessage(), e);
         }
+        // 执行子类关闭
         try {
             doClose();
         } catch (Throwable e) {
@@ -340,6 +436,7 @@ public void close() {
         }
     }
 
+    @Override
     public void close(int timeout) {
         ExecutorUtil.gracefulShutdown(executor, timeout);
         close();
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractCodec.java
index 76cb8ab549..d6ce325af2 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractCodec.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractCodec.java
@@ -30,12 +30,22 @@
 
 /**
  * AbstractCodec
+ *
+ * Codec 抽象类
  */
 public abstract class AbstractCodec implements Codec2 {
 
     private static final Logger logger = LoggerFactory.getLogger(AbstractCodec.class);
 
+    /**
+     * 校验消息长度
+     *
+     * @param channel 通道
+     * @param size 消息长度
+     * @throws IOException 当 IO 发生异常
+     */
     protected static void checkPayload(Channel channel, long size) throws IOException {
+        // 加载
         int payload = Constants.DEFAULT_PAYLOAD;
         if (channel != null && channel.getUrl() != null) {
             payload = channel.getUrl().getParameter(Constants.PAYLOAD_KEY, Constants.DEFAULT_PAYLOAD);
@@ -47,10 +57,22 @@ protected static void checkPayload(Channel channel, long size) throws IOExceptio
         }
     }
 
+    /**
+     * 获得 Serialization 对象
+     *
+     * @param channel 通道
+     * @return Serialization 对象
+     */
     protected Serialization getSerialization(Channel channel) {
         return CodecSupport.getSerialization(channel.getUrl());
     }
 
+    /**
+     * 是否为客户端侧的通道
+     *
+     * @param channel 通道
+     * @return 是否
+     */
     protected boolean isClientSide(Channel channel) {
         String side = (String) channel.getAttribute(Constants.SIDE_KEY);
         if ("client".equals(side)) {
@@ -58,12 +80,11 @@ protected boolean isClientSide(Channel channel) {
         } else if ("server".equals(side)) {
             return false;
         } else {
+            //
             InetSocketAddress address = channel.getRemoteAddress();
             URL url = channel.getUrl();
             boolean client = url.getPort() == address.getPort()
-                    && NetUtils.filterLocalHost(url.getIp()).equals(
-                    NetUtils.filterLocalHost(address.getAddress()
-                            .getHostAddress()));
+                    && NetUtils.filterLocalHost(url.getIp()).equals(NetUtils.filterLocalHost(address.getAddress().getHostAddress()));
             channel.setAttribute(Constants.SIDE_KEY, client ? "client"
                     : "server");
             return client;
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractEndpoint.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractEndpoint.java
index e8ccfe4f37..141f3bf94f 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractEndpoint.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractEndpoint.java
@@ -29,15 +29,24 @@
 
 /**
  * AbstractEndpoint
+ *
+ * Endpoint 抽象类
  */
 public abstract class AbstractEndpoint extends AbstractPeer implements Resetable {
 
     private static final Logger logger = LoggerFactory.getLogger(AbstractEndpoint.class);
 
+    /**
+     * 编解码器
+     */
     private Codec2 codec;
-
+    /**
+     * 超时时间
+     */
     private int timeout;
-
+    /**
+     * 连接超时时间
+     */
     private int connectTimeout;
 
     public AbstractEndpoint(URL url, ChannelHandler handler) {
@@ -47,21 +56,28 @@ public AbstractEndpoint(URL url, ChannelHandler handler) {
         this.connectTimeout = url.getPositiveParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT);
     }
 
+    /**
+     * 获得编解码器
+     *
+     * @param url URL
+     * @return 编解码器
+     */
     protected static Codec2 getChannelCodec(URL url) {
         String codecName = url.getParameter(Constants.CODEC_KEY, "telnet");
-        if (ExtensionLoader.getExtensionLoader(Codec2.class).hasExtension(codecName)) {
+        if (ExtensionLoader.getExtensionLoader(Codec2.class).hasExtension(codecName)) { // 例如,在 DubboProtocol 中,会获得 DubboCodec
             return ExtensionLoader.getExtensionLoader(Codec2.class).getExtension(codecName);
         } else {
-            return new CodecAdapter(ExtensionLoader.getExtensionLoader(Codec.class)
-                    .getExtension(codecName));
+            return new CodecAdapter(ExtensionLoader.getExtensionLoader(Codec.class).getExtension(codecName));
         }
     }
 
+    @Override
     public void reset(URL url) {
         if (isClosed()) {
             throw new IllegalStateException("Failed to reset parameters "
                     + url + ", cause: Channel closed. channel: " + getLocalAddress());
         }
+        // 重置 `timeout` 属性
         try {
             if (url.hasParameter(Constants.TIMEOUT_KEY)) {
                 int t = url.getParameter(Constants.TIMEOUT_KEY, 0);
@@ -72,6 +88,7 @@ public void reset(URL url) {
         } catch (Throwable t) {
             logger.error(t.getMessage(), t);
         }
+        // 重置 `connectTimeout` 属性
         try {
             if (url.hasParameter(Constants.CONNECT_TIMEOUT_KEY)) {
                 int t = url.getParameter(Constants.CONNECT_TIMEOUT_KEY, 0);
@@ -82,6 +99,7 @@ public void reset(URL url) {
         } catch (Throwable t) {
             logger.error(t.getMessage(), t);
         }
+        // 重置 `codec` 属性
         try {
             if (url.hasParameter(Constants.CODEC_KEY)) {
                 this.codec = getChannelCodec(url);
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractPeer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractPeer.java
index a44c2c9f96..f6ead0f19e 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractPeer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractPeer.java
@@ -25,16 +25,31 @@
 
 /**
  * AbstractPeer
+ *
+ * Peer 抽象类
  */
 public abstract class AbstractPeer implements Endpoint, ChannelHandler {
 
+    /**
+     * 通道处理器
+     */
     private final ChannelHandler handler;
-
+    /**
+     * URL
+     */
     private volatile URL url;
-
+    /**
+     * 正在关闭
+     *
+     * {@link #startClose()}
+     */
     // closing closed means the process is being closed and close is finished
     private volatile boolean closing;
-
+    /**
+     * 关闭完成
+     *
+     * {@link #close()}
+     */
     private volatile boolean closed;
 
     public AbstractPeer(URL url, ChannelHandler handler) {
@@ -48,18 +63,22 @@ public AbstractPeer(URL url, ChannelHandler handler) {
         this.handler = handler;
     }
 
+    @Override
     public void send(Object message) throws RemotingException {
         send(message, url.getParameter(Constants.SENT_KEY, false));
     }
 
+    @Override
     public void close() {
         closed = true;
     }
 
+    @Override
     public void close(int timeout) {
         close();
     }
 
+    @Override
     public void startClose() {
         if (isClosed()) {
             return;
@@ -67,6 +86,7 @@ public void startClose() {
         closing = true;
     }
 
+    @Override
     public URL getUrl() {
         return url;
     }
@@ -78,8 +98,14 @@ protected void setUrl(URL url) {
         this.url = url;
     }
 
+    /**
+     * 获得通道处理器
+     *
+     * @return 通道处理器
+     */
+    @Override
     public ChannelHandler getChannelHandler() {
-        if (handler instanceof ChannelHandlerDelegate) {
+        if (handler instanceof ChannelHandlerDelegate) { // 获得真实的 ChannelHandler
             return ((ChannelHandlerDelegate) handler).getHandler();
         } else {
             return handler;
@@ -103,6 +129,7 @@ public ChannelHandler getDelegateHandler() {
         return handler;
     }
 
+    @Override
     public boolean isClosed() {
         return closed;
     }
@@ -111,6 +138,7 @@ public boolean isClosing() {
         return closing && !closed;
     }
 
+    @Override
     public void connected(Channel ch) throws RemotingException {
         if (closed) {
             return;
@@ -118,10 +146,12 @@ public void connected(Channel ch) throws RemotingException {
         handler.connected(ch);
     }
 
+    @Override
     public void disconnected(Channel ch) throws RemotingException {
         handler.disconnected(ch);
     }
 
+    @Override
     public void sent(Channel ch, Object msg) throws RemotingException {
         if (closed) {
             return;
@@ -129,6 +159,7 @@ public void sent(Channel ch, Object msg) throws RemotingException {
         handler.sent(ch, msg);
     }
 
+    @Override
     public void received(Channel ch, Object msg) throws RemotingException {
         if (closed) {
             return;
@@ -136,7 +167,9 @@ public void received(Channel ch, Object msg) throws RemotingException {
         handler.received(ch, msg);
     }
 
+    @Override
     public void caught(Channel ch, Throwable ex) throws RemotingException {
         handler.caught(ch, ex);
     }
+
 }
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractServer.java
index d0b4842dc8..565206efa5 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractServer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/AbstractServer.java
@@ -36,29 +36,53 @@
 
 /**
  * AbstractServer
+ *
+ * Server 抽象类
  */
 public abstract class AbstractServer extends AbstractEndpoint implements Server {
 
     protected static final String SERVER_THREAD_POOL_NAME = "DubboServerHandler";
+
     private static final Logger logger = LoggerFactory.getLogger(AbstractServer.class);
+
+    /**
+     * 线程池
+     */
     ExecutorService executor;
+    /**
+     * 服务地址
+     */
     private InetSocketAddress localAddress;
+    /**
+     * 绑定地址
+     */
     private InetSocketAddress bindAddress;
+    /**
+     * 服务器最大可接受连接数
+     */
     private int accepts;
-    private int idleTimeout = 600; //600 seconds
+    /**
+     * 空闲超时时间,单位:毫秒
+     */
+    private int idleTimeout; //600 seconds
 
     public AbstractServer(URL url, ChannelHandler handler) throws RemotingException {
         super(url, handler);
+        // 服务地址
         localAddress = getUrl().toInetSocketAddress();
-
+        // 绑定地址
         String bindIp = getUrl().getParameter(Constants.BIND_IP_KEY, getUrl().getHost());
         int bindPort = getUrl().getParameter(Constants.BIND_PORT_KEY, getUrl().getPort());
         if (url.getParameter(Constants.ANYHOST_KEY, false) || NetUtils.isInvalidLocalHost(bindIp)) {
             bindIp = NetUtils.ANYHOST;
         }
         bindAddress = new InetSocketAddress(bindIp, bindPort);
+        // 服务器最大可接受连接数
         this.accepts = url.getParameter(Constants.ACCEPTS_KEY, Constants.DEFAULT_ACCEPTS);
+        // 空闲超时时间
         this.idleTimeout = url.getParameter(Constants.IDLE_TIMEOUT_KEY, Constants.DEFAULT_IDLE_TIMEOUT);
+
+        // 开启服务器
         try {
             doOpen();
             if (logger.isInfoEnabled()) {
@@ -68,6 +92,8 @@ public AbstractServer(URL url, ChannelHandler handler) throws RemotingException
             throw new RemotingException(url.toInetSocketAddress(), null, "Failed to bind " + getClass().getSimpleName()
                     + " on " + getLocalAddress() + ", cause: " + t.getMessage(), t);
         }
+
+        // 获得线程池
         //fixme replace this with better method
         DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
         executor = (ExecutorService) dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY, Integer.toString(url.getPort()));
@@ -77,10 +103,12 @@ public AbstractServer(URL url, ChannelHandler handler) throws RemotingException
 
     protected abstract void doClose() throws Throwable;
 
+    @Override
     public void reset(URL url) {
         if (url == null) {
             return;
         }
+        // 重置 `accepts` 属性
         try {
             if (url.hasParameter(Constants.ACCEPTS_KEY)) {
                 int a = url.getParameter(Constants.ACCEPTS_KEY, 0);
@@ -101,6 +129,7 @@ public void reset(URL url) {
         } catch (Throwable t) {
             logger.error(t.getMessage(), t);
         }
+        // 重置 `executor` 属性
         try {
             if (url.hasParameter(Constants.THREADS_KEY)
                     && executor instanceof ThreadPoolExecutor && !executor.isShutdown()) {
@@ -109,14 +138,14 @@ public void reset(URL url) {
                 int max = threadPoolExecutor.getMaximumPoolSize();
                 int core = threadPoolExecutor.getCorePoolSize();
                 if (threads > 0 && (threads != max || threads != core)) {
-                    if (threads < core) {
+                    if (threads < core) { // 缩小
                         threadPoolExecutor.setCorePoolSize(threads);
-                        if (core == max) {
+                        if (core == max) { // 相等,说明是 FixedThreadPool ,同时设置
                             threadPoolExecutor.setMaximumPoolSize(threads);
                         }
-                    } else {
+                    } else { // 扩大
                         threadPoolExecutor.setMaximumPoolSize(threads);
-                        if (core == max) {
+                        if (core == max) { // 相等,说明是 FixedThreadPool ,同时设置
                             threadPoolExecutor.setCorePoolSize(threads);
                         }
                     }
@@ -125,11 +154,15 @@ public void reset(URL url) {
         } catch (Throwable t) {
             logger.error(t.getMessage(), t);
         }
+        // 设置 `url` 属性
         super.setUrl(getUrl().addParameters(url.getParameters()));
     }
 
+    @Override
     public void send(Object message, boolean sent) throws RemotingException {
+        // 获得所有的客户端的通道
         Collection<Channel> channels = getChannels();
+        // 群发消息
         for (Channel channel : channels) {
             if (channel.isConnected()) {
                 channel.send(message, sent);
@@ -137,6 +170,7 @@ public void send(Object message, boolean sent) throws RemotingException {
         }
     }
 
+    @Override
     public void close() {
         if (logger.isInfoEnabled()) {
             logger.info("Close " + getClass().getSimpleName() + " bind " + getBindAddress() + ", export " + getLocalAddress());
@@ -154,11 +188,13 @@ public void close() {
         }
     }
 
+    @Override
     public void close(int timeout) {
         ExecutorUtil.gracefulShutdown(executor, timeout);
         close();
     }
 
+    @Override
     public InetSocketAddress getLocalAddress() {
         return localAddress;
     }
@@ -184,12 +220,14 @@ public void connected(Channel ch) throws RemotingException {
             return;
         }
 
+        // 超过上限,关闭新的链接
         Collection<Channel> channels = getChannels();
         if (accepts > 0 && channels.size() > accepts) {
             logger.error("Close channel " + ch + ", cause: The server " + ch.getLocalAddress() + " connections greater than max config " + accepts);
-            ch.close();
+            ch.close(); // 关闭新的链接
             return;
         }
+        // 连接
         super.connected(ch);
     }
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelDelegate.java
index df69efb0d1..57f262b0b6 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelDelegate.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelDelegate.java
@@ -25,6 +25,7 @@
 
 /**
  * ChannelDelegate
+ *
  */
 public class ChannelDelegate implements Channel {
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerAdapter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerAdapter.java
index 08f710f5eb..647beac245 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerAdapter.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerAdapter.java
@@ -22,22 +22,19 @@
 
 /**
  * ChannelHandlerAdapter.
+ *
+ * 通道处理器适配器,每个方法为空实现。
  */
 public class ChannelHandlerAdapter implements ChannelHandler {
 
-    public void connected(Channel channel) throws RemotingException {
-    }
+    @Override public void connected(Channel channel) throws RemotingException { }
 
-    public void disconnected(Channel channel) throws RemotingException {
-    }
+    @Override public void disconnected(Channel channel) throws RemotingException { }
 
-    public void sent(Channel channel, Object message) throws RemotingException {
-    }
+    @Override public void sent(Channel channel, Object message) { }
 
-    public void received(Channel channel, Object message) throws RemotingException {
-    }
+    @Override public void received(Channel channel, Object message) throws RemotingException { }
 
-    public void caught(Channel channel, Throwable exception) throws RemotingException {
-    }
+    @Override public void caught(Channel channel, Throwable exception) throws RemotingException { }
 
 }
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerDelegate.java
index 08c9f07840..b7c5b100f1 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerDelegate.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerDelegate.java
@@ -18,6 +18,14 @@
 
 import com.alibaba.dubbo.remoting.ChannelHandler;
 
+/**
+ * 通道处理器装饰者
+ */
 public interface ChannelHandlerDelegate extends ChannelHandler {
+
+    /**
+     * @return 通道处理器
+     */
     ChannelHandler getHandler();
-}
+
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerDispatcher.java
index 6a2d9817c9..7097a1fa8b 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerDispatcher.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ChannelHandlerDispatcher.java
@@ -27,11 +27,16 @@
 
 /**
  * ChannelListenerDispatcher
+ *
+ * 通道处理器集合,是一组 ChannelHandler 的集合。
  */
 public class ChannelHandlerDispatcher implements ChannelHandler {
 
     private static final Logger logger = LoggerFactory.getLogger(ChannelHandlerDispatcher.class);
 
+    /**
+     * 通道处理器集合
+     */
     private final Collection<ChannelHandler> channelHandlers = new CopyOnWriteArraySet<ChannelHandler>();
 
     public ChannelHandlerDispatcher() {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ClientDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ClientDelegate.java
index b49af09b40..2c4cfbb99e 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ClientDelegate.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ClientDelegate.java
@@ -25,9 +25,14 @@
 
 /**
  * ClientDelegate
+ *
+ * 客户端装饰者
  */
 public class ClientDelegate implements Client {
 
+    /**
+     * 客户端
+     */
     private transient Client client;
 
     public ClientDelegate() {
@@ -48,6 +53,7 @@ public void setClient(Client client) {
         this.client = client;
     }
 
+    @Override
     public void reset(URL url) {
         client.reset(url);
     }
@@ -57,58 +63,72 @@ public void reset(com.alibaba.dubbo.common.Parameters parameters) {
         reset(getUrl().addParameters(parameters.getParameters()));
     }
 
+    @Override
     public URL getUrl() {
         return client.getUrl();
     }
 
+    @Override
     public InetSocketAddress getRemoteAddress() {
         return client.getRemoteAddress();
     }
 
+    @Override
     public void reconnect() throws RemotingException {
         client.reconnect();
     }
 
+    @Override
     public ChannelHandler getChannelHandler() {
         return client.getChannelHandler();
     }
 
+    @Override
     public boolean isConnected() {
         return client.isConnected();
     }
 
+    @Override
     public InetSocketAddress getLocalAddress() {
         return client.getLocalAddress();
     }
 
+    @Override
     public boolean hasAttribute(String key) {
         return client.hasAttribute(key);
     }
 
+    @Override
     public void send(Object message) throws RemotingException {
         client.send(message);
     }
 
+    @Override
     public Object getAttribute(String key) {
         return client.getAttribute(key);
     }
 
+    @Override
     public void setAttribute(String key, Object value) {
         client.setAttribute(key, value);
     }
 
+    @Override
     public void send(Object message, boolean sent) throws RemotingException {
         client.send(message, sent);
     }
 
+    @Override
     public void removeAttribute(String key) {
         client.removeAttribute(key);
     }
 
+    @Override
     public void close() {
         client.close();
     }
 
+    @Override
     public void close(int timeout) {
         client.close(timeout);
     }
@@ -118,6 +138,7 @@ public void startClose() {
         client.startClose();
     }
 
+    @Override
     public boolean isClosed() {
         return client.isClosed();
     }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/CodecSupport.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/CodecSupport.java
index a9b0c1a63a..7b71537dc9 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/CodecSupport.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/CodecSupport.java
@@ -29,13 +29,27 @@
 import java.util.Map;
 import java.util.Set;
 
+/**
+ * 编解码工具类,提供查询 Serialization 的功能
+ */
 public class CodecSupport {
 
     private static final Logger logger = LoggerFactory.getLogger(CodecSupport.class);
+
+    /**
+     * 序列化对象集合
+     * key:序列化类型编号 {@link Serialization#getContentTypeId()}
+     */
     private static Map<Byte, Serialization> ID_SERIALIZATION_MAP = new HashMap<Byte, Serialization>();
+    /**
+     * 序列化名集合
+     * key:序列化类型编号 {@link Serialization#getContentTypeId()}
+     * value: 序列化拓展名
+     */
     private static Map<Byte, String> ID_SERIALIZATIONNAME_MAP = new HashMap<Byte, String>();
 
     static {
+        // 基于 Dubbo SPI ,初始化
         Set<String> supportedExtensions = ExtensionLoader.getExtensionLoader(Serialization.class).getSupportedExtensions();
         for (String name : supportedExtensions) {
             Serialization serialization = ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(name);
@@ -66,7 +80,9 @@ public static Serialization getSerialization(URL url) {
 
     public static Serialization getSerialization(URL url, Byte id) throws IOException {
         Serialization serialization = getSerializationById(id);
-        String serializationName = url.getParameter(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION);
+        String serializationName = url.getParameter(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION); // 默认,hessian2
+        // 出于安全的目的,针对 JDK 的序列化方式(对应编号为 3、4、7),检查连接到服务器的 URL 和实际传输的数据,协议是否一致。
+        // https://github.com/apache/incubator-dubbo/issues/1138
         // Check if "serialization id" passed from network matches the id on this side(only take effect for JDK serialization), for security purpose.
         if (serialization == null
                 || ((id == 3 || id == 7 || id == 4) && !(serializationName.equals(ID_SERIALIZATIONNAME_MAP.get(id))))) {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/DecodeHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/DecodeHandler.java
index 36a9c166d7..0a05074f2e 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/DecodeHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/DecodeHandler.java
@@ -26,6 +26,9 @@
 import com.alibaba.dubbo.remoting.exchange.Request;
 import com.alibaba.dubbo.remoting.exchange.Response;
 
+/**
+ * 解码处理器,处理接收到的消息,实现了 Decodeable 接口的情况。
+ */
 public class DecodeHandler extends AbstractChannelHandlerDelegate {
 
     private static final Logger log = LoggerFactory.getLogger(DecodeHandler.class);
@@ -34,6 +37,7 @@ public DecodeHandler(ChannelHandler handler) {
         super(handler);
     }
 
+    @Override
     public void received(Channel channel, Object message) throws RemotingException {
         if (message instanceof Decodeable) {
             decode(message);
@@ -53,18 +57,13 @@ public void received(Channel channel, Object message) throws RemotingException {
     private void decode(Object message) {
         if (message != null && message instanceof Decodeable) {
             try {
-                ((Decodeable) message).decode();
+                ((Decodeable) message).decode(); // 解析消息
                 if (log.isDebugEnabled()) {
-                    log.debug(new StringBuilder(32).append("Decode decodeable message ")
-                            .append(message.getClass().getName()).toString());
+                    log.debug(new StringBuilder(32).append("Decode decodeable message ").append(message.getClass().getName()).toString());
                 }
             } catch (Throwable e) {
                 if (log.isWarnEnabled()) {
-                    log.warn(
-                            new StringBuilder(32)
-                                    .append("Call Decodeable.decode failed: ")
-                                    .append(e.getMessage()).toString(),
-                            e);
+                    log.warn(new StringBuilder(32).append("Call Decodeable.decode failed: ").append(e.getMessage()).toString(), e);
                 }
             } // ~ end of catch
         } // ~ end of if
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/MultiMessageHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/MultiMessageHandler.java
index 80ff9a3b62..7de45ff24e 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/MultiMessageHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/MultiMessageHandler.java
@@ -22,6 +22,7 @@
 import com.alibaba.dubbo.remoting.exchange.support.MultiMessage;
 
 /**
+ * 多消息处理器
  *
  * @see MultiMessage
  */
@@ -34,7 +35,7 @@ public MultiMessageHandler(ChannelHandler handler) {
     @SuppressWarnings("unchecked")
     @Override
     public void received(Channel channel, Object message) throws RemotingException {
-        if (message instanceof MultiMessage) {
+        if (message instanceof MultiMessage) { // 多消息
             MultiMessage list = (MultiMessage) message;
             for (Object obj : list) {
                 handler.received(channel, obj);
@@ -43,4 +44,5 @@ public void received(Channel channel, Object message) throws RemotingException {
             handler.received(channel, message);
         }
     }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ServerDelegate.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ServerDelegate.java
index 5be3b6d60b..a41de85894 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ServerDelegate.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/ServerDelegate.java
@@ -28,10 +28,13 @@
 /**
  * ServerDelegate
  *
- *
+ * 服务器装饰者
  */
 public class ServerDelegate implements Server {
 
+    /**
+     * 服务器
+     */
     private transient Server server;
 
     public ServerDelegate() {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/codec/CodecAdapter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/codec/CodecAdapter.java
index 0466fffad8..f1f0487d7a 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/codec/CodecAdapter.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/codec/CodecAdapter.java
@@ -27,8 +27,14 @@
 
 import java.io.IOException;
 
+/**
+ * Codec 适配器,将 Codec 适配成 Codec2
+ */
 public class CodecAdapter implements Codec2 {
 
+    /**
+     * codec
+     */
     private Codec codec;
 
     public CodecAdapter(Codec codec) {
@@ -36,24 +42,33 @@ public CodecAdapter(Codec codec) {
         this.codec = codec;
     }
 
+    @Override
     public void encode(Channel channel, ChannelBuffer buffer, Object message)
             throws IOException {
         UnsafeByteArrayOutputStream os = new UnsafeByteArrayOutputStream(1024);
+        // 编码
         codec.encode(channel, os, message);
+        // 写入 buffer
         buffer.writeBytes(os.toByteArray());
     }
 
+    @Override
     public Object decode(Channel channel, ChannelBuffer buffer) throws IOException {
+        // 读取字节到数组
         byte[] bytes = new byte[buffer.readableBytes()];
         int savedReaderIndex = buffer.readerIndex();
         buffer.readBytes(bytes);
+        // 解码
         UnsafeByteArrayInputStream is = new UnsafeByteArrayInputStream(bytes);
         Object result = codec.decode(channel, is);
+        // 设置最新的开始读取位置
         buffer.readerIndex(savedReaderIndex + is.position());
+        // 返回是否要进一步读取
         return result == Codec.NEED_MORE_INPUT ? DecodeResult.NEED_MORE_INPUT : result;
     }
 
     public Codec getCodec() {
         return codec;
     }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/codec/TransportCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/codec/TransportCodec.java
index 71368754a3..0852edaded 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/codec/TransportCodec.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/codec/TransportCodec.java
@@ -32,23 +32,32 @@
 
 /**
  * TransportCodec
+ *
+ * 传输编解码器,使用 Serialization 进行序列化/反序列化。
  */
 public class TransportCodec extends AbstractCodec {
 
+    @Override
     public void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException {
+        // 获得反序列化的 ObjectOutput 对象
         OutputStream output = new ChannelBufferOutputStream(buffer);
         ObjectOutput objectOutput = getSerialization(channel).serialize(channel.getUrl(), output);
+        // 写入 ObjectOutput
         encodeData(channel, objectOutput, message);
         objectOutput.flushBuffer();
+        // 释放
         if (objectOutput instanceof Cleanable) {
             ((Cleanable) objectOutput).cleanup();
         }
     }
 
+    @Override
     public Object decode(Channel channel, ChannelBuffer buffer) throws IOException {
+        // 反序列化
         InputStream input = new ChannelBufferInputStream(buffer);
         ObjectInput objectInput = getSerialization(channel).deserialize(channel.getUrl(), input);
         Object object = decodeData(channel, objectInput);
+        // 释放
         if (objectInput instanceof Cleanable) {
             ((Cleanable) objectInput).cleanup();
         }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java
index 0c5e876597..09839f5e92 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java
@@ -21,7 +21,11 @@
 import com.alibaba.dubbo.remoting.Channel;
 import com.alibaba.dubbo.remoting.ChannelHandler;
 
+/**
+ * 通道事件 Runnable
+ */
 public class ChannelEventRunnable implements Runnable {
+
     private static final Logger logger = LoggerFactory.getLogger(ChannelEventRunnable.class);
 
     private final ChannelHandler handler;
@@ -50,6 +54,7 @@ public ChannelEventRunnable(Channel channel, ChannelHandler handler, ChannelStat
         this.exception = exception;
     }
 
+    @Override
     public void run() {
         switch (state) {
             case CONNECTED:
@@ -98,7 +103,7 @@ public void run() {
     /**
      * ChannelState
      *
-     *
+     * 通道事件类型
      */
     public enum ChannelState {
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelHandlers.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelHandlers.java
index e1e9b0876e..e50898a025 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelHandlers.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelHandlers.java
@@ -24,8 +24,14 @@
 import com.alibaba.dubbo.remoting.exchange.support.header.HeartbeatHandler;
 import com.alibaba.dubbo.remoting.transport.MultiMessageHandler;
 
+/**
+ * 通道处理器工厂
+ */
 public class ChannelHandlers {
 
+    /**
+     * 单例
+     */
     private static ChannelHandlers INSTANCE = new ChannelHandlers();
 
     protected ChannelHandlers() {
@@ -39,12 +45,16 @@ protected static ChannelHandlers getInstance() {
         return INSTANCE;
     }
 
-    static void setTestingChannelHandlers(ChannelHandlers instance) {
+    static void setTestingChannelHandlers(ChannelHandlers instance) { // for testing
         INSTANCE = instance;
     }
 
     protected ChannelHandler wrapInternal(ChannelHandler handler, URL url) {
-        return new MultiMessageHandler(new HeartbeatHandler(ExtensionLoader.getExtensionLoader(Dispatcher.class)
-                .getAdaptiveExtension().dispatch(handler, url)));
+        return new MultiMessageHandler(
+                new HeartbeatHandler(
+                        ExtensionLoader.getExtensionLoader(Dispatcher.class).getAdaptiveExtension().dispatch(handler, url)
+                )
+        );
     }
-}
+
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/WrappedChannelHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/WrappedChannelHandler.java
index e9975c8d3f..70eaf22512 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/WrappedChannelHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/WrappedChannelHandler.java
@@ -32,23 +32,39 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
+/**
+ * 包装的 WrappedChannelHandler 实现类
+ */
 public class WrappedChannelHandler implements ChannelHandlerDelegate {
 
     protected static final Logger logger = LoggerFactory.getLogger(WrappedChannelHandler.class);
 
+    /**
+     * 共享线程池
+     */
     protected static final ExecutorService SHARED_EXECUTOR = Executors.newCachedThreadPool(new NamedThreadFactory("DubboSharedHandler", true));
 
+    /**
+     * 线程池
+     */
     protected final ExecutorService executor;
-
+    /**
+     * 通道处理器
+     */
     protected final ChannelHandler handler;
-
+    /**
+     * URL
+     */
     protected final URL url;
 
     public WrappedChannelHandler(ChannelHandler handler, URL url) {
         this.handler = handler;
         this.url = url;
+
+        // 创建线程池
         executor = (ExecutorService) ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
 
+        // 添加线程池到 DataStore 中
         String componentKey = Constants.EXECUTOR_SERVICE_COMPONENT_KEY;
         if (Constants.CONSUMER_SIDE.equalsIgnoreCase(url.getParameter(Constants.SIDE_KEY))) {
             componentKey = Constants.CONSUMER_SIDE;
@@ -59,30 +75,35 @@ public WrappedChannelHandler(ChannelHandler handler, URL url) {
 
     public void close() {
         try {
-            if (executor instanceof ExecutorService) {
-                ((ExecutorService) executor).shutdown();
+            if (executor != null) {
+                executor.shutdown();
             }
         } catch (Throwable t) {
             logger.warn("fail to destroy thread pool of server: " + t.getMessage(), t);
         }
     }
 
+    @Override
     public void connected(Channel channel) throws RemotingException {
         handler.connected(channel);
     }
 
+    @Override
     public void disconnected(Channel channel) throws RemotingException {
         handler.disconnected(channel);
     }
 
+    @Override
     public void sent(Channel channel, Object message) throws RemotingException {
         handler.sent(channel, message);
     }
 
+    @Override
     public void received(Channel channel, Object message) throws RemotingException {
         handler.received(channel, message);
     }
 
+    @Override
     public void caught(Channel channel, Throwable exception) throws RemotingException {
         handler.caught(channel, exception);
     }
@@ -91,6 +112,7 @@ public ExecutorService getExecutor() {
         return executor;
     }
 
+    @Override
     public ChannelHandler getHandler() {
         if (handler instanceof ChannelHandlerDelegate) {
             return ((ChannelHandlerDelegate) handler).getHandler();
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/all/AllChannelHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/all/AllChannelHandler.java
index 1dade1abfc..6b283619e0 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/all/AllChannelHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/all/AllChannelHandler.java
@@ -30,12 +30,16 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.RejectedExecutionException;
 
+/**
+ * `all` 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。
+ */
 public class AllChannelHandler extends WrappedChannelHandler {
 
     public AllChannelHandler(ChannelHandler handler, URL url) {
         super(handler, url);
     }
 
+    @Override
     public void connected(Channel channel) throws RemotingException {
         ExecutorService cexecutor = getExecutorService();
         try {
@@ -54,6 +58,7 @@ public void disconnected(Channel channel) throws RemotingException {
         }
     }
 
+    @SuppressWarnings("Duplicates")
     public void received(Channel channel, Object message) throws RemotingException {
         ExecutorService cexecutor = getExecutorService();
         try {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/all/AllDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/all/AllDispatcher.java
index 823c50479a..97eea2f341 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/all/AllDispatcher.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/all/AllDispatcher.java
@@ -22,6 +22,7 @@
 
 /**
  * default thread pool configure
+ *
  */
 public class AllDispatcher implements Dispatcher {
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/connection/ConnectionOrderedChannelHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/connection/ConnectionOrderedChannelHandler.java
index ed7681182f..f3ca145e78 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/connection/ConnectionOrderedChannelHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/connection/ConnectionOrderedChannelHandler.java
@@ -71,6 +71,7 @@ public void disconnected(Channel channel) throws RemotingException {
         }
     }
 
+    @SuppressWarnings("Duplicates")
     public void received(Channel channel, Object message) throws RemotingException {
         ExecutorService cexecutor = executor;
         if (cexecutor == null || cexecutor.isShutdown()) {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/connection/ConnectionOrderedDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/connection/ConnectionOrderedDispatcher.java
index 1209ccd36f..e4de8fa36f 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/connection/ConnectionOrderedDispatcher.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/connection/ConnectionOrderedDispatcher.java
@@ -22,6 +22,7 @@
 
 /**
  * connect disconnect ensure the order
+ *
  */
 public class ConnectionOrderedDispatcher implements Dispatcher {
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/direct/DirectDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/direct/DirectDispatcher.java
index bd19271720..3ffc63e689 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/direct/DirectDispatcher.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/direct/DirectDispatcher.java
@@ -22,6 +22,7 @@
 
 /**
  * Direct dispatcher
+ *
  */
 public class DirectDispatcher implements Dispatcher {
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/execution/ExecutionChannelHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/execution/ExecutionChannelHandler.java
index fd1261cde2..a217197baf 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/execution/ExecutionChannelHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/execution/ExecutionChannelHandler.java
@@ -35,14 +35,15 @@ public ExecutionChannelHandler(ChannelHandler handler, URL url) {
         super(handler, url);
     }
 
-    public void connected(Channel channel) throws RemotingException {
+    public void connected(Channel channel) {
         executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.CONNECTED));
     }
 
-    public void disconnected(Channel channel) throws RemotingException {
+    public void disconnected(Channel channel) {
         executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.DISCONNECTED));
     }
 
+    @SuppressWarnings("Duplicates")
     public void received(Channel channel, Object message) throws RemotingException {
     	try {
             executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/execution/ExecutionDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/execution/ExecutionDispatcher.java
index a62bee7b4f..6119e55cf8 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/execution/ExecutionDispatcher.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/execution/ExecutionDispatcher.java
@@ -22,6 +22,7 @@
 
 /**
  * In addition to sending all the use thread pool processing
+ *
  */
 public class ExecutionDispatcher implements Dispatcher {
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/message/MessageOnlyChannelHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/message/MessageOnlyChannelHandler.java
index 457d763c0d..d8513e7287 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/message/MessageOnlyChannelHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/message/MessageOnlyChannelHandler.java
@@ -33,6 +33,7 @@ public MessageOnlyChannelHandler(ChannelHandler handler, URL url) {
         super(handler, url);
     }
 
+    @Override
     public void received(Channel channel, Object message) throws RemotingException {
         ExecutorService cexecutor = executor;
         if (cexecutor == null || cexecutor.isShutdown()) {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/message/MessageOnlyDispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/message/MessageOnlyDispatcher.java
index 0435c9b5f5..c4392624de 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/message/MessageOnlyDispatcher.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/message/MessageOnlyDispatcher.java
@@ -22,6 +22,7 @@
 
 /**
  * Only message receive uses the thread pool.
+ *
  */
 public class MessageOnlyDispatcher implements Dispatcher {
 
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpBinder.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpBinder.java
index 1b3e1e7849..b13ed2bbbf 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpBinder.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpBinder.java
@@ -23,6 +23,8 @@
 
 /**
  * HttpBinder
+ *
+ * HTTP 绑定起接口
  */
 @SPI("jetty")
 public interface HttpBinder {
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpHandler.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpHandler.java
index ccc7f2f889..bba0acc77d 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpHandler.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpHandler.java
@@ -23,16 +23,20 @@
 
 /**
  * http invocation handler.
+ *
+ * HTTP 处理器接口
  */
 public interface HttpHandler {
 
     /**
      * invoke.
      *
-     * @param request  request.
-     * @param response response.
-     * @throws IOException
-     * @throws ServletException
+     * 处理器请求
+     *
+     * @param request  request. 请求
+     * @param response response. 响应
+     * @throws IOException 当 IO 发生异常
+     * @throws ServletException 当 Servlet 发生异常
      */
     void handle(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;
 
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpServer.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpServer.java
index 7b7f0b644a..7abbc55e7d 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpServer.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/HttpServer.java
@@ -21,6 +21,9 @@
 
 import java.net.InetSocketAddress;
 
+/**
+ * HTTP 服务器接口
+ */
 public interface HttpServer extends Resetable {
 
     /**
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpBinder.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpBinder.java
index b75eabd910..6bfe03eabb 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpBinder.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpBinder.java
@@ -23,9 +23,12 @@
 
 /**
  * JettyHttpTransporter
+ *
+ * JettyHttpServer 绑定器实现类
  */
 public class JettyHttpBinder implements HttpBinder {
 
+    @Override
     public HttpServer bind(URL url, HttpHandler handler) {
         return new JettyHttpServer(url, handler);
     }
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpServer.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpServer.java
index ed137f15ca..cc2f97124f 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpServer.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/jetty/JettyHttpServer.java
@@ -35,46 +35,61 @@
 import org.mortbay.log.StdErrLog;
 import org.mortbay.thread.QueuedThreadPool;
 
+/**
+ * 基于 Jetty 的 HTTP 服务器实现类
+ */
 public class JettyHttpServer extends AbstractHttpServer {
 
     private static final Logger logger = LoggerFactory.getLogger(JettyHttpServer.class);
 
+    /**
+     * 内嵌的 Jetty 服务器
+     */
     private Server server;
-
+    /**
+     * URL 对象
+     */
     private URL url;
 
     public JettyHttpServer(URL url, final HttpHandler handler) {
         super(url, handler);
         this.url = url;
+
+        // 设置日志的配置
         // TODO we should leave this setting to slf4j
         // we must disable the debug logging for production use
         Log.setLog(new StdErrLog());
         Log.getLog().setDebugEnabled(false);
 
+        // 注册 HttpHandler 到 DispatcherServlet 中
         DispatcherServlet.addHttpHandler(url.getParameter(Constants.BIND_PORT_KEY, url.getPort()), handler);
 
+        // 创建线程池
         int threads = url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS);
         QueuedThreadPool threadPool = new QueuedThreadPool();
         threadPool.setDaemon(true);
         threadPool.setMaxThreads(threads);
         threadPool.setMinThreads(threads);
 
+        // 创建 Jetty Connector 对象
         SelectChannelConnector connector = new SelectChannelConnector();
-
         String bindIp = url.getParameter(Constants.BIND_IP_KEY, url.getHost());
         if (!url.isAnyHost() && NetUtils.isValidLocalHost(bindIp)) {
             connector.setHost(bindIp);
         }
         connector.setPort(url.getParameter(Constants.BIND_PORT_KEY, url.getPort()));
 
+        // 创建内嵌的 Jetty 对象
         server = new Server();
         server.setThreadPool(threadPool);
         server.addConnector(connector);
 
+        // 添加 DispatcherServlet 到 Jetty 中
         ServletHandler servletHandler = new ServletHandler();
         ServletHolder servletHolder = servletHandler.addServletWithMapping(DispatcherServlet.class, "/*");
         servletHolder.setInitOrder(2);
 
+        // 添加 ServletContext 对象,到 ServletManager 中
         // dubbo's original impl can't support the use of ServletContext
 //        server.addHandler(servletHandler);
         // TODO Context.SESSIONS is the best option here?
@@ -82,6 +97,7 @@ public JettyHttpServer(URL url, final HttpHandler handler) {
         context.setServletHandler(servletHandler);
         ServletManager.getInstance().addServletContext(url.getParameter(Constants.BIND_PORT_KEY, url.getPort()), context.getServletContext());
 
+        // 启动 Jetty
         try {
             server.start();
         } catch (Exception e) {
@@ -90,12 +106,15 @@ public JettyHttpServer(URL url, final HttpHandler handler) {
         }
     }
 
+    @Override
     public void close() {
+        // 标记关闭
         super.close();
 
-        //
+        // 移除 ServletContext 对象
         ServletManager.getInstance().removeServletContext(url.getParameter(Constants.BIND_PORT_KEY, url.getPort()));
 
+        // 关闭 Jetty
         if (server != null) {
             try {
                 server.stop();
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/BootstrapListener.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/BootstrapListener.java
index 8407405e3d..eb2d78d094 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/BootstrapListener.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/BootstrapListener.java
@@ -25,11 +25,14 @@
  */
 public class BootstrapListener implements ServletContextListener {
 
+    @Override
     public void contextInitialized(ServletContextEvent servletContextEvent) {
         ServletManager.getInstance().addServletContext(ServletManager.EXTERNAL_SERVER_PORT, servletContextEvent.getServletContext());
     }
 
+    @Override
     public void contextDestroyed(ServletContextEvent servletContextEvent) {
         ServletManager.getInstance().removeServletContext(ServletManager.EXTERNAL_SERVER_PORT);
     }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/DispatcherServlet.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/DispatcherServlet.java
index 2f9425310c..0a8aa06a63 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/DispatcherServlet.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/DispatcherServlet.java
@@ -28,34 +28,60 @@
 
 /**
  * Service dispatcher Servlet.
+ *
+ * 服务调度 Servlet
  */
 public class DispatcherServlet extends HttpServlet {
 
     private static final long serialVersionUID = 5766349180380479888L;
+
+    /**
+     * 处理器集合
+     *
+     * key:服务器端口
+     */
     private static final Map<Integer, HttpHandler> handlers = new ConcurrentHashMap<Integer, HttpHandler>();
+    /**
+     * 单例
+     */
     private static DispatcherServlet INSTANCE;
 
     public DispatcherServlet() {
         DispatcherServlet.INSTANCE = this;
     }
 
+    public static DispatcherServlet getInstance() {
+        return INSTANCE;
+    }
+
+    /**
+     * 添加处理器
+     *
+     * @param port 服务器端口
+     * @param processor 处理器
+     */
     public static void addHttpHandler(int port, HttpHandler processor) {
         handlers.put(port, processor);
     }
 
+    /**
+     * 移除处理器
+     *
+     * @param port 服务器端口
+     */
     public static void removeHttpHandler(int port) {
         handlers.remove(port);
     }
 
-    public static DispatcherServlet getInstance() {
-        return INSTANCE;
-    }
-
+    @Override
     protected void service(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
+        // 获得处理器
         HttpHandler handler = handlers.get(request.getLocalPort());
+        // 处理器不存在,报错
         if (handler == null) {// service not found.
             response.sendError(HttpServletResponse.SC_NOT_FOUND, "Service not found.");
+        // 处理请求
         } else {
             handler.handle(request, response);
         }
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpServer.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpServer.java
index 3f9d4b614c..add9b35ecd 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpServer.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletHttpServer.java
@@ -21,10 +21,15 @@
 import com.alibaba.dubbo.remoting.http.HttpHandler;
 import com.alibaba.dubbo.remoting.http.support.AbstractHttpServer;
 
+/**
+ * 基于 Servlet 的服务器实现类
+ */
 public class ServletHttpServer extends AbstractHttpServer {
 
     public ServletHttpServer(URL url, HttpHandler handler) {
         super(url, handler);
+
+        // 注册 HttpHandler 到 DispatcherServlet 中
         DispatcherServlet.addHttpHandler(url.getParameter(Constants.BIND_PORT_KEY, 8080), handler);
     }
 
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletManager.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletManager.java
index 24dbd2ff91..c528e49d65 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletManager.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/servlet/ServletManager.java
@@ -22,29 +22,57 @@
 
 /**
  * TODO this may not be a pretty elegant solution,
+ * 这可能不是一个非常优雅的解决方案。
  *
+ * Servlet 管理器
  */
 public class ServletManager {
 
+    /**
+     * 外部服务器端口,用于 `servlet` 的服务器端口
+     */
     public static final int EXTERNAL_SERVER_PORT = -1234;
 
+    /**
+     * 单例
+     */
     private static final ServletManager instance = new ServletManager();
-
+    /**
+     * ServletContext 集合
+     */
     private final Map<Integer, ServletContext> contextMap = new ConcurrentHashMap<Integer, ServletContext>();
 
     public static ServletManager getInstance() {
         return instance;
     }
 
+    /**
+     * 添加 ServletContext 对象
+     *
+     * @param port 服务器端口
+     * @param servletContext ServletContext 对象
+     */
     public void addServletContext(int port, ServletContext servletContext) {
         contextMap.put(port, servletContext);
     }
 
+    /**
+     * 移除 ServletContext 对象
+     *
+     * @param port 服务器端口
+     */
     public void removeServletContext(int port) {
         contextMap.remove(port);
     }
 
+    /**
+     * 获得 ServletContext 对象
+     *
+     * @param port 服务器端口
+     * @return ServletContext 对象
+     */
     public ServletContext getServletContext(int port) {
         return contextMap.get(port);
     }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/support/AbstractHttpServer.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/support/AbstractHttpServer.java
index fec16a5e18..e3d457309d 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/support/AbstractHttpServer.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/support/AbstractHttpServer.java
@@ -24,13 +24,22 @@
 
 /**
  * AbstractHttpServer
+ *
+ * HTTP 服务器抽象类
  */
 public abstract class AbstractHttpServer implements HttpServer {
 
+    /**
+     * URL 对象
+     */
     private final URL url;
-
+    /**
+     * 处理器
+     */
     private final HttpHandler handler;
-
+    /**
+     * 是否关闭
+     */
     private volatile boolean closed;
 
     public AbstractHttpServer(URL url, HttpHandler handler) {
@@ -44,33 +53,41 @@ public AbstractHttpServer(URL url, HttpHandler handler) {
         this.handler = handler;
     }
 
+    @Override
     public HttpHandler getHttpHandler() {
         return handler;
     }
 
+    @Override
     public URL getUrl() {
         return url;
     }
 
+    @Override
     public void reset(URL url) {
     }
 
+    @Override
     public boolean isBound() {
         return true;
     }
 
+    @Override
     public InetSocketAddress getLocalAddress() {
         return url.toInetSocketAddress();
     }
 
+    @Override
     public void close() {
         closed = true;
     }
 
+    @Override
     public void close(int timeout) {
         close();
     }
 
+    @Override
     public boolean isClosed() {
         return closed;
     }
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/tomcat/TomcatHttpBinder.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/tomcat/TomcatHttpBinder.java
index 8ff017e029..ddbda4fbb4 100755
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/tomcat/TomcatHttpBinder.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/tomcat/TomcatHttpBinder.java
@@ -21,8 +21,12 @@
 import com.alibaba.dubbo.remoting.http.HttpHandler;
 import com.alibaba.dubbo.remoting.http.HttpServer;
 
+/**
+ * TomcatHttpServer 绑定器实现类
+ */
 public class TomcatHttpBinder implements HttpBinder {
 
+    @Override
     public HttpServer bind(URL url, HttpHandler handler) {
         return new TomcatHttpServer(url, handler);
     }
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/tomcat/TomcatHttpServer.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/tomcat/TomcatHttpServer.java
index 7ed61f9046..514bf5f5a7 100755
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/tomcat/TomcatHttpServer.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/com/alibaba/dubbo/remoting/http/tomcat/TomcatHttpServer.java
@@ -31,42 +31,52 @@
 
 import java.io.File;
 
+/**
+ * 基于 Tomcat 的 HTTP 服务器实现类
+ */
 public class TomcatHttpServer extends AbstractHttpServer {
 
     private static final Logger logger = LoggerFactory.getLogger(TomcatHttpServer.class);
 
+    /**
+     * 内嵌的 Tomcat 对象
+     */
     private final Tomcat tomcat;
-
+    /**
+     * URL 对象
+     */
     private final URL url;
 
     public TomcatHttpServer(URL url, final HttpHandler handler) {
         super(url, handler);
-
         this.url = url;
+
+        // 注册 HttpHandler 到 DispatcherServlet 中
         DispatcherServlet.addHttpHandler(url.getPort(), handler);
+
+        // 创建内嵌的 Tomcat 对象
         String baseDir = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();
         tomcat = new Tomcat();
         tomcat.setBaseDir(baseDir);
         tomcat.setPort(url.getPort());
-        tomcat.getConnector().setProperty(
-                "maxThreads", String.valueOf(url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS)));
+        tomcat.getConnector().setProperty("maxThreads", String.valueOf(url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS))); // 最大线程数
 //        tomcat.getConnector().setProperty(
 //                "minSpareThreads", String.valueOf(url.getParameter(Constants.THREADS_KEY, Constants.DEFAULT_THREADS)));
-
-        tomcat.getConnector().setProperty(
-                "maxConnections", String.valueOf(url.getParameter(Constants.ACCEPTS_KEY, -1)));
-
-        tomcat.getConnector().setProperty("URIEncoding", "UTF-8");
-        tomcat.getConnector().setProperty("connectionTimeout", "60000");
-
+        tomcat.getConnector().setProperty("maxConnections", String.valueOf(url.getParameter(Constants.ACCEPTS_KEY, -1))); // 最大连接池
+        tomcat.getConnector().setProperty("URIEncoding", "UTF-8"); // 编码为 UTF-8
+        tomcat.getConnector().setProperty("connectionTimeout", "60000"); // 连接超时,60 秒
         tomcat.getConnector().setProperty("maxKeepAliveRequests", "-1");
         tomcat.getConnector().setProtocol("org.apache.coyote.http11.Http11NioProtocol");
 
+        // 添加 DispatcherServlet 到 Tomcat 中
         Context context = tomcat.addContext("/", baseDir);
         Tomcat.addServlet(context, "dispatcher", new DispatcherServlet());
         context.addServletMapping("/*", "dispatcher");
+
+        // 添加 ServletContext 对象,到 ServletManager 中
         ServletManager.getInstance().addServletContext(url.getPort(), context.getServletContext());
 
+        // 启动 Tomcat
         try {
             tomcat.start();
         } catch (LifecycleException e) {
@@ -74,11 +84,15 @@ public TomcatHttpServer(URL url, final HttpHandler handler) {
         }
     }
 
+    @Override
     public void close() {
+        // 标记关闭
         super.close();
 
+        // 移除 ServletContext 对象
         ServletManager.getInstance().removeServletContext(url.getPort());
 
+        // 关闭 Tomcat
         try {
             tomcat.stop();
         } catch (Exception e) {
diff --git a/dubbo-remoting/dubbo-remoting-mina/src/main/java/com/alibaba/dubbo/remoting/transport/mina/MinaClient.java b/dubbo-remoting/dubbo-remoting-mina/src/main/java/com/alibaba/dubbo/remoting/transport/mina/MinaClient.java
index 3aa2c8cd61..5071b4ea81 100644
--- a/dubbo-remoting/dubbo-remoting-mina/src/main/java/com/alibaba/dubbo/remoting/transport/mina/MinaClient.java
+++ b/dubbo-remoting/dubbo-remoting-mina/src/main/java/com/alibaba/dubbo/remoting/transport/mina/MinaClient.java
@@ -64,7 +64,7 @@ public MinaClient(final URL url, final ChannelHandler handler) throws RemotingEx
     }
 
     @Override
-    protected void doOpen() throws Throwable {
+    protected void doOpen() {
         connectorKey = getUrl().toFullString();
         SocketConnector c = connectors.get(connectorKey);
         if (c != null) {
@@ -148,7 +148,7 @@ public void operationComplete(IoFuture future) {
     }
 
     @Override
-    protected void doDisConnect() throws Throwable {
+    protected void doDisConnect() {
         try {
             MinaChannel.removeChannelIfDisconnectd(session);
         } catch (Throwable t) {
diff --git a/dubbo-remoting/dubbo-remoting-mina/src/main/java/com/alibaba/dubbo/remoting/transport/mina/MinaCodecAdapter.java b/dubbo-remoting/dubbo-remoting-mina/src/main/java/com/alibaba/dubbo/remoting/transport/mina/MinaCodecAdapter.java
index 7d3dfd2a8b..1f798fefdb 100644
--- a/dubbo-remoting/dubbo-remoting-mina/src/main/java/com/alibaba/dubbo/remoting/transport/mina/MinaCodecAdapter.java
+++ b/dubbo-remoting/dubbo-remoting-mina/src/main/java/com/alibaba/dubbo/remoting/transport/mina/MinaCodecAdapter.java
@@ -58,17 +58,19 @@ public MinaCodecAdapter(Codec2 codec, URL url, ChannelHandler handler) {
         this.bufferSize = b >= Constants.MIN_BUFFER_SIZE && b <= Constants.MAX_BUFFER_SIZE ? b : Constants.DEFAULT_BUFFER_SIZE;
     }
 
+    @Override
     public ProtocolEncoder getEncoder() {
         return encoder;
     }
 
+    @Override
     public ProtocolDecoder getDecoder() {
         return decoder;
     }
 
     private class InternalEncoder implements ProtocolEncoder {
 
-        public void dispose(IoSession session) throws Exception {
+        public void dispose(IoSession session) {
         }
 
         public void encode(IoSession session, Object msg, ProtocolEncoderOutput out) throws Exception {
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyBackedChannelBuffer.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyBackedChannelBuffer.java
index bcfbb5193e..2f28067a84 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyBackedChannelBuffer.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyBackedChannelBuffer.java
@@ -26,6 +26,9 @@
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 
+/**
+ * 基于 Netty ChannelBuffer 的通道 Buffer 实现类
+ */
 public class NettyBackedChannelBuffer implements ChannelBuffer {
 
     private org.jboss.netty.buffer.ChannelBuffer buffer;
@@ -39,36 +42,37 @@ public NettyBackedChannelBuffer(org.jboss.netty.buffer.ChannelBuffer buffer) {
         return buffer;
     }
 
+    @Override
     public int capacity() {
         return buffer.capacity();
     }
 
-
+    @Override
     public ChannelBuffer copy(int index, int length) {
         return new NettyBackedChannelBuffer(buffer.copy(index, length));
     }
 
-
+    @Override
     public ChannelBufferFactory factory() {
         return NettyBackedChannelBufferFactory.getInstance();
     }
 
-
+    @Override
     public byte getByte(int index) {
         return buffer.getByte(index);
     }
 
-
+    @Override
     public void getBytes(int index, byte[] dst, int dstIndex, int length) {
         buffer.getBytes(index, dst, dstIndex, length);
     }
 
-
+    @Override
     public void getBytes(int index, ByteBuffer dst) {
         buffer.getBytes(index, dst);
     }
 
-
+    @Override
     public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
         // careful
         byte[] data = new byte[length];
@@ -76,32 +80,32 @@ public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
         dst.setBytes(dstIndex, data, 0, length);
     }
 
-
+    @Override
     public void getBytes(int index, OutputStream dst, int length) throws IOException {
         buffer.getBytes(index, dst, length);
     }
 
-
+    @Override
     public boolean isDirect() {
         return buffer.isDirect();
     }
 
-
+    @Override
     public void setByte(int index, int value) {
         buffer.setByte(index, value);
     }
 
-
+    @Override
     public void setBytes(int index, byte[] src, int srcIndex, int length) {
         buffer.setBytes(index, src, srcIndex, length);
     }
 
-
+    @Override
     public void setBytes(int index, ByteBuffer src) {
         buffer.setBytes(index, src);
     }
 
-
+    @Override
     public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
         // careful
         byte[] data = new byte[length];
@@ -109,27 +113,27 @@ public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
         setBytes(0, data, index, length);
     }
 
-
+    @Override
     public int setBytes(int index, InputStream src, int length) throws IOException {
         return buffer.setBytes(index, src, length);
     }
 
-
+    @Override
     public ByteBuffer toByteBuffer(int index, int length) {
         return buffer.toByteBuffer(index, length);
     }
 
-
+    @Override
     public byte[] array() {
         return buffer.array();
     }
 
-
+    @Override
     public boolean hasArray() {
         return buffer.hasArray();
     }
 
-
+    @Override
     public int arrayOffset() {
         return buffer.arrayOffset();
     }
@@ -137,38 +141,38 @@ public int arrayOffset() {
 
     // AbstractChannelBuffer
 
-
+    @Override
     public void clear() {
         buffer.clear();
     }
 
-
+    @Override
     public ChannelBuffer copy() {
         return new NettyBackedChannelBuffer(buffer.copy());
     }
 
-
+    @Override
     public void discardReadBytes() {
         buffer.discardReadBytes();
     }
 
-
+    @Override
     public void ensureWritableBytes(int writableBytes) {
         buffer.ensureWritableBytes(writableBytes);
     }
 
-
+    @Override
     public void getBytes(int index, byte[] dst) {
         buffer.getBytes(index, dst);
     }
 
-
+    @Override
     public void getBytes(int index, ChannelBuffer dst) {
         // careful
         getBytes(index, dst, dst.writableBytes());
     }
 
-
+    @Override
     public void getBytes(int index, ChannelBuffer dst, int length) {
         // careful
         if (length > dst.writableBytes()) {
@@ -178,53 +182,53 @@ public void getBytes(int index, ChannelBuffer dst, int length) {
         dst.writerIndex(dst.writerIndex() + length);
     }
 
-
+    @Override
     public void markReaderIndex() {
         buffer.markReaderIndex();
     }
 
-
+    @Override
     public void markWriterIndex() {
         buffer.markWriterIndex();
     }
 
-
+    @Override
     public boolean readable() {
         return buffer.readable();
     }
 
-
+    @Override
     public int readableBytes() {
         return buffer.readableBytes();
     }
 
-
+    @Override
     public byte readByte() {
         return buffer.readByte();
     }
 
-
+    @Override
     public void readBytes(byte[] dst) {
         buffer.readBytes(dst);
     }
 
-
+    @Override
     public void readBytes(byte[] dst, int dstIndex, int length) {
         buffer.readBytes(dst, dstIndex, length);
     }
 
-
+    @Override
     public void readBytes(ByteBuffer dst) {
         buffer.readBytes(dst);
     }
 
-
+    @Override
     public void readBytes(ChannelBuffer dst) {
         // careful
         readBytes(dst, dst.writableBytes());
     }
 
-
+    @Override
     public void readBytes(ChannelBuffer dst, int length) {
         // carefule
         if (length > dst.writableBytes()) {
@@ -234,7 +238,7 @@ public void readBytes(ChannelBuffer dst, int length) {
         dst.writerIndex(dst.writerIndex() + length);
     }
 
-
+    @Override
     public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
         // careful
         if (readableBytes() < length) {
@@ -245,48 +249,48 @@ public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
         dst.setBytes(dstIndex, data, 0, length);
     }
 
-
+    @Override
     public ChannelBuffer readBytes(int length) {
         return new NettyBackedChannelBuffer(buffer.readBytes(length));
     }
 
-
+    @Override
     public void resetReaderIndex() {
         buffer.resetReaderIndex();
     }
 
-
+    @Override
     public void resetWriterIndex() {
         buffer.resetWriterIndex();
     }
 
-
+    @Override
     public int readerIndex() {
         return buffer.readerIndex();
     }
 
-
+    @Override
     public void readerIndex(int readerIndex) {
         buffer.readerIndex(readerIndex);
     }
 
-
+    @Override
     public void readBytes(OutputStream dst, int length) throws IOException {
         buffer.readBytes(dst, length);
     }
 
-
+    @Override
     public void setBytes(int index, byte[] src) {
         buffer.setBytes(index, src);
     }
 
-
+    @Override
     public void setBytes(int index, ChannelBuffer src) {
         // careful
         setBytes(index, src, src.readableBytes());
     }
 
-
+    @Override
     public void setBytes(int index, ChannelBuffer src, int length) {
         // careful
         if (length > src.readableBytes()) {
@@ -296,58 +300,58 @@ public void setBytes(int index, ChannelBuffer src, int length) {
         src.readerIndex(src.readerIndex() + length);
     }
 
-
+    @Override
     public void setIndex(int readerIndex, int writerIndex) {
         buffer.setIndex(readerIndex, writerIndex);
     }
 
-
+    @Override
     public void skipBytes(int length) {
         buffer.skipBytes(length);
     }
 
-
+    @Override
     public ByteBuffer toByteBuffer() {
         return buffer.toByteBuffer();
     }
 
-
+    @Override
     public boolean writable() {
         return buffer.writable();
     }
 
-
+    @Override
     public int writableBytes() {
         return buffer.writableBytes();
     }
 
-
+    @Override
     public void writeByte(int value) {
         buffer.writeByte(value);
     }
 
-
+    @Override
     public void writeBytes(byte[] src) {
         buffer.writeBytes(src);
     }
 
-
+    @Override
     public void writeBytes(byte[] src, int index, int length) {
         buffer.writeBytes(src, index, length);
     }
 
-
+    @Override
     public void writeBytes(ByteBuffer src) {
         buffer.writeBytes(src);
     }
 
-
+    @Override
     public void writeBytes(ChannelBuffer src) {
         // careful
         writeBytes(src, src.readableBytes());
     }
 
-
+    @Override
     public void writeBytes(ChannelBuffer src, int length) {
         // careful
         if (length > src.readableBytes()) {
@@ -357,7 +361,7 @@ public void writeBytes(ChannelBuffer src, int length) {
         src.readerIndex(src.readerIndex() + length);
     }
 
-
+    @Override
     public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
         // careful
         byte[] data = new byte[length];
@@ -365,22 +369,22 @@ public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
         writeBytes(data, 0, length);
     }
 
-
+    @Override
     public int writeBytes(InputStream src, int length) throws IOException {
         return buffer.writeBytes(src, length);
     }
 
-
+    @Override
     public int writerIndex() {
         return buffer.writerIndex();
     }
 
-
+    @Override
     public void writerIndex(int writerIndex) {
         buffer.writerIndex(writerIndex);
     }
 
-
+    @Override
     public int compareTo(ChannelBuffer o) {
         return ChannelBuffers.compare(this, o);
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyBackedChannelBufferFactory.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyBackedChannelBufferFactory.java
index f35909eb74..d391204e8c 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyBackedChannelBufferFactory.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyBackedChannelBufferFactory.java
@@ -34,20 +34,24 @@ public static ChannelBufferFactory getInstance() {
         return INSTANCE;
     }
 
-
+    @Override
     public ChannelBuffer getBuffer(int capacity) {
-        return new NettyBackedChannelBuffer(ChannelBuffers.dynamicBuffer(capacity));
+        return new NettyBackedChannelBuffer(ChannelBuffers.dynamicBuffer(capacity)); // ChannelBuffers 为 `org.jboss.netty.buffer` 包下
     }
 
-
+    @Override
     public ChannelBuffer getBuffer(byte[] array, int offset, int length) {
-        org.jboss.netty.buffer.ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(length);
+        // 创建 Netty3 ChannelBuffer 对象
+        org.jboss.netty.buffer.ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(length); // ChannelBuffers 为 `org.jboss.netty.buffer` 包下
+        // 写入数据
         buffer.writeBytes(array, offset, length);
+        // 创建 NettyBackedChannelBuffer 对象
         return new NettyBackedChannelBuffer(buffer);
     }
 
-
+    @Override
     public ChannelBuffer getBuffer(ByteBuffer nioBuffer) {
-        return new NettyBackedChannelBuffer(ChannelBuffers.wrappedBuffer(nioBuffer));
+        return new NettyBackedChannelBuffer(ChannelBuffers.wrappedBuffer(nioBuffer)); // ChannelBuffers 为 `org.jboss.netty.buffer` 包下
     }
+
 }
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyChannel.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyChannel.java
index a866db2b39..d1e1f3ebbd 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyChannel.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyChannel.java
@@ -38,10 +38,18 @@
 
     private static final Logger logger = LoggerFactory.getLogger(NettyChannel.class);
 
+    /**
+     * 通道集合
+     */
     private static final ConcurrentMap<org.jboss.netty.channel.Channel, NettyChannel> channelMap = new ConcurrentHashMap<org.jboss.netty.channel.Channel, NettyChannel>();
 
+    /**
+     * 通道
+     */
     private final org.jboss.netty.channel.Channel channel;
-
+    /**
+     * 属性集合
+     */
     private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
 
     private NettyChannel(org.jboss.netty.channel.Channel channel, URL url, ChannelHandler handler) {
@@ -52,6 +60,14 @@ private NettyChannel(org.jboss.netty.channel.Channel channel, URL url, ChannelHa
         this.channel = channel;
     }
 
+    /**
+     * 创建 NettyChannel 对象
+     *
+     * @param ch 通道
+     * @param url URL
+     * @param handler 处理器
+     * @return NettyChannel 对象
+     */
     static NettyChannel getOrAddChannel(org.jboss.netty.channel.Channel ch, URL url, ChannelHandler handler) {
         if (ch == null) {
             return null;
@@ -59,8 +75,8 @@ static NettyChannel getOrAddChannel(org.jboss.netty.channel.Channel ch, URL url,
         NettyChannel ret = channelMap.get(ch);
         if (ret == null) {
             NettyChannel nc = new NettyChannel(ch, url, handler);
-            if (ch.isConnected()) {
-                ret = channelMap.putIfAbsent(ch, nc);
+            if (ch.isConnected()) { // 连接中
+                ret = channelMap.putIfAbsent(ch, nc); // 添加到 channelMap
             }
             if (ret == null) {
                 ret = nc;
@@ -69,9 +85,14 @@ static NettyChannel getOrAddChannel(org.jboss.netty.channel.Channel ch, URL url,
         return ret;
     }
 
+    /**
+     * 移除 NettyChannel 对象
+     *
+     * @param ch 通道
+     */
     static void removeChannelIfDisconnected(org.jboss.netty.channel.Channel ch) {
-        if (ch != null && !ch.isConnected()) {
-            channelMap.remove(ch);
+        if (ch != null && !ch.isConnected()) { // 未连接
+            channelMap.remove(ch); // 移除出channelMap
         }
     }
 
@@ -88,16 +109,20 @@ public boolean isConnected() {
     }
 
     public void send(Object message, boolean sent) throws RemotingException {
+        // 检查连接状态
         super.send(message, sent);
 
         boolean success = true;
         int timeout = 0;
         try {
+            // 发送消息
             ChannelFuture future = channel.write(message);
+            // 等待发送成功
             if (sent) {
                 timeout = getUrl().getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
                 success = future.await(timeout);
             }
+            // 若发生异常,抛出
             Throwable cause = future.getCause();
             if (cause != null) {
                 throw cause;
@@ -106,6 +131,7 @@ public void send(Object message, boolean sent) throws RemotingException {
             throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e);
         }
 
+        // 发送失败,抛出异常
         if (!success) {
             throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress()
                     + "in timeout(" + timeout + "ms) limit");
@@ -113,21 +139,25 @@ public void send(Object message, boolean sent) throws RemotingException {
     }
 
     public void close() {
+        // 标记关闭
         try {
             super.close();
         } catch (Exception e) {
             logger.warn(e.getMessage(), e);
         }
+        // 移除连接
         try {
             removeChannelIfDisconnected(channel);
         } catch (Exception e) {
             logger.warn(e.getMessage(), e);
         }
+        // 清空属性 attributes
         try {
             attributes.clear();
         } catch (Exception e) {
             logger.warn(e.getMessage(), e);
         }
+        // 关闭真正的通道 channel
         try {
             if (logger.isInfoEnabled()) {
                 logger.info("Close netty channel " + channel);
@@ -138,14 +168,17 @@ public void close() {
         }
     }
 
+    @Override
     public boolean hasAttribute(String key) {
         return attributes.containsKey(key);
     }
 
+    @Override
     public Object getAttribute(String key) {
         return attributes.get(key);
     }
 
+    @Override
     public void setAttribute(String key, Object value) {
         if (value == null) { // The null value unallowed in the ConcurrentHashMap.
             attributes.remove(key);
@@ -154,6 +187,7 @@ public void setAttribute(String key, Object value) {
         }
     }
 
+    @Override
     public void removeAttribute(String key) {
         attributes.remove(key);
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyClient.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyClient.java
index 404fbb898c..e502a703e3 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyClient.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyClient.java
@@ -42,6 +42,7 @@
 /**
  * NettyClient.
  */
+@SuppressWarnings("Duplicates")
 public class NettyClient extends AbstractClient {
 
     private static final Logger logger = LoggerFactory.getLogger(NettyClient.class);
@@ -51,46 +52,60 @@
     private static final ChannelFactory channelFactory = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(new NamedThreadFactory("NettyClientBoss", true)),
             Executors.newCachedThreadPool(new NamedThreadFactory("NettyClientWorker", true)),
             Constants.DEFAULT_IO_THREADS);
+
     private ClientBootstrap bootstrap;
 
-    private volatile Channel channel; // volatile, please copy reference to use
+    private volatile org.jboss.netty.channel.Channel channel; // volatile, please copy reference to use
 
     public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException {
         super(url, wrapChannelHandler(url, handler));
     }
 
     @Override
-    protected void doOpen() throws Throwable {
+    protected void doOpen() {
+        // 设置日志工厂
         NettyHelper.setNettyLoggerFactory();
+
+        // 实例化 ServerBootstrap
         bootstrap = new ClientBootstrap(channelFactory);
+        // 设置可选项
         // config
         // @see org.jboss.netty.channel.socket.SocketChannelConfig
         bootstrap.setOption("keepAlive", true);
         bootstrap.setOption("tcpNoDelay", true);
         bootstrap.setOption("connectTimeoutMillis", getTimeout());
+
+        // 创建 NettyHandler 对象
         final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
+
+        // 设置责任链路
         bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
             public ChannelPipeline getPipeline() {
+                // 创建 NettyCodecAdapter 对象
                 NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this);
                 ChannelPipeline pipeline = Channels.pipeline();
-                pipeline.addLast("decoder", adapter.getDecoder());
-                pipeline.addLast("encoder", adapter.getEncoder());
-                pipeline.addLast("handler", nettyHandler);
+                pipeline.addLast("decoder", adapter.getDecoder()); // 解码
+                pipeline.addLast("encoder", adapter.getEncoder()); // 编码
+                pipeline.addLast("handler", nettyHandler); // 处理器
                 return pipeline;
             }
         });
     }
 
+    @Override
     protected void doConnect() throws Throwable {
         long start = System.currentTimeMillis();
+        // 连接服务器
         ChannelFuture future = bootstrap.connect(getConnectAddress());
         try {
+            // 等待连接成功或者超时
             boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS);
-
+            // 连接成功
             if (ret && future.isSuccess()) {
                 Channel newChannel = future.getChannel();
                 newChannel.setInterestOps(Channel.OP_READ_WRITE);
                 try {
+                    // 关闭老的连接
                     // Close old channel
                     Channel oldChannel = NettyClient.this.channel; // copy reference
                     if (oldChannel != null) {
@@ -104,6 +119,7 @@ protected void doConnect() throws Throwable {
                         }
                     }
                 } finally {
+                    // 若 NettyClient 被关闭,关闭连接
                     if (NettyClient.this.isClosed()) {
                         try {
                             if (logger.isInfoEnabled()) {
@@ -114,13 +130,16 @@ protected void doConnect() throws Throwable {
                             NettyClient.this.channel = null;
                             NettyChannel.removeChannelIfDisconnected(newChannel);
                         }
+                    // 设置新连接
                     } else {
                         NettyClient.this.channel = newChannel;
                     }
                 }
+            // 发生异常,抛出 RemotingException 异常
             } else if (future.getCause() != null) {
                 throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
                         + getRemoteAddress() + ", error message is:" + future.getCause().getMessage(), future.getCause());
+            // 无结果(连接超时),抛出 RemotingException 异常
             } else {
                 throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
                         + getRemoteAddress() + " client-side timeout "
@@ -128,6 +147,7 @@ protected void doConnect() throws Throwable {
                         + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion());
             }
         } finally {
+            // 未连接,取消任务
             if (!isConnected()) {
                 future.cancel();
             }
@@ -135,7 +155,7 @@ protected void doConnect() throws Throwable {
     }
 
     @Override
-    protected void doDisConnect() throws Throwable {
+    protected void doDisConnect() {
         try {
             NettyChannel.removeChannelIfDisconnected(channel);
         } catch (Throwable t) {
@@ -144,7 +164,7 @@ protected void doDisConnect() throws Throwable {
     }
 
     @Override
-    protected void doClose() throws Throwable {
+    protected void doClose() {
         /*try {
             bootstrap.releaseExternalResources();
         } catch (Throwable t) {
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyCodecAdapter.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyCodecAdapter.java
index 9fbfad51d9..e8b8294319 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyCodecAdapter.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyCodecAdapter.java
@@ -40,22 +40,37 @@
  */
 final class NettyCodecAdapter {
 
+    /**
+     * Netty 编码器
+     */
     private final ChannelHandler encoder = new InternalEncoder();
-
+    /**
+     * Netty 解码器
+     */
     private final ChannelHandler decoder = new InternalDecoder();
 
+    /**
+     * Dubbo 编解码器
+     */
     private final Codec2 codec;
-
+    /**
+     * Dubbo URL
+     */
     private final URL url;
-
+    /**
+     * 网络读写缓冲区大小
+     */
     private final int bufferSize;
-
+    /**
+     * Dubbo ChannelHandler
+     */
     private final com.alibaba.dubbo.remoting.ChannelHandler handler;
 
     public NettyCodecAdapter(Codec2 codec, URL url, com.alibaba.dubbo.remoting.ChannelHandler handler) {
         this.codec = codec;
         this.url = url;
         this.handler = handler;
+        // 设置 `bufferSize`
         int b = url.getPositiveParameter(Constants.BUFFER_KEY, Constants.DEFAULT_BUFFER_SIZE);
         this.bufferSize = b >= Constants.MIN_BUFFER_SIZE && b <= Constants.MAX_BUFFER_SIZE ? b : Constants.DEFAULT_BUFFER_SIZE;
     }
@@ -73,58 +88,67 @@ public ChannelHandler getDecoder() {
 
         @Override
         protected Object encode(ChannelHandlerContext ctx, Channel ch, Object msg) throws Exception {
-            com.alibaba.dubbo.remoting.buffer.ChannelBuffer buffer =
-                    com.alibaba.dubbo.remoting.buffer.ChannelBuffers.dynamicBuffer(1024);
+            // 创建 HeapChannelBuffer 对象
+            com.alibaba.dubbo.remoting.buffer.ChannelBuffer buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.dynamicBuffer(1024);
+            // 获得 NettyChannel 对象
             NettyChannel channel = NettyChannel.getOrAddChannel(ch, url, handler);
             try {
+                // 编码
                 codec.encode(channel, buffer, msg);
             } finally {
+                // 移除 NettyChannel 对象,若断开连接
                 NettyChannel.removeChannelIfDisconnected(ch);
             }
+            // 返回 Netty ChannelBuffer 对象
             return ChannelBuffers.wrappedBuffer(buffer.toByteBuffer());
         }
+
     }
 
     private class InternalDecoder extends SimpleChannelUpstreamHandler {
 
-        private com.alibaba.dubbo.remoting.buffer.ChannelBuffer buffer =
-                com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
+        /**
+         * 未读完的消息 Buffer
+         */
+        private com.alibaba.dubbo.remoting.buffer.ChannelBuffer buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
 
         @Override
         public void messageReceived(ChannelHandlerContext ctx, MessageEvent event) throws Exception {
+            // 跳过非 ChannelBuffer
             Object o = event.getMessage();
             if (!(o instanceof ChannelBuffer)) {
                 ctx.sendUpstream(event);
                 return;
             }
 
+            // 无可读,跳过
             ChannelBuffer input = (ChannelBuffer) o;
             int readable = input.readableBytes();
             if (readable <= 0) {
                 return;
             }
 
+            // 合并 `buffer` + `input` 成 `message`
             com.alibaba.dubbo.remoting.buffer.ChannelBuffer message;
-            if (buffer.readable()) {
+            if (buffer.readable()) { // 有未读完的,需要拼接
                 if (buffer instanceof DynamicChannelBuffer) {
                     buffer.writeBytes(input.toByteBuffer());
                     message = buffer;
-                } else {
+                } else { // Netty3 ChannelBuffer ,转成 DynamicChannelBuffer 。
                     int size = buffer.readableBytes() + input.readableBytes();
-                    message = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.dynamicBuffer(
-                            size > bufferSize ? size : bufferSize);
+                    message = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.dynamicBuffer(size > bufferSize ? size : bufferSize);
                     message.writeBytes(buffer, buffer.readableBytes());
                     message.writeBytes(input.toByteBuffer());
                 }
-            } else {
-                message = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.wrappedBuffer(
-                        input.toByteBuffer());
+            } else { // 无未读完的,直接创建
+                message = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.wrappedBuffer(input.toByteBuffer());
             }
 
+            // 获得 NettyChannel 对象
             NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(), url, handler);
+            // 循环解析,直到结束
             Object msg;
             int saveReaderIndex;
-
             try {
                 // decode object.
                 do {
@@ -138,7 +162,9 @@ public void messageReceived(ChannelHandlerContext ctx, MessageEvent event) throw
                     if (msg == Codec2.DecodeResult.NEED_MORE_INPUT) {
                         message.readerIndex(saveReaderIndex);
                         break;
+                    // 解码到消息,触发一条消息
                     } else {
+                        //is it possible to go here ? 芋艿:不可能,哈哈哈
                         if (saveReaderIndex == message.readerIndex()) {
                             buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
                             throw new IOException("Decode without read data.");
@@ -149,18 +175,21 @@ public void messageReceived(ChannelHandlerContext ctx, MessageEvent event) throw
                     }
                 } while (message.readable());
             } finally {
+                // 有剩余可读的,压缩并缓存
                 if (message.readable()) {
                     message.discardReadBytes();
                     buffer = message;
+                // 无剩余的,设置空 Buffer
                 } else {
                     buffer = com.alibaba.dubbo.remoting.buffer.ChannelBuffers.EMPTY_BUFFER;
                 }
+                // 移除 NettyChannel 对象,若断开连接
                 NettyChannel.removeChannelIfDisconnected(ctx.getChannel());
             }
         }
 
         @Override
-        public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
+        public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
             ctx.sendUpstream(e);
         }
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyHandler.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyHandler.java
index ae6dfbc870..581549af00 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyHandler.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyHandler.java
@@ -38,10 +38,17 @@
 @Sharable
 public class NettyHandler extends SimpleChannelHandler {
 
+    /**
+     * Dubbo Channel 集合
+     */
     private final Map<String, Channel> channels = new ConcurrentHashMap<String, Channel>(); // <ip:port, channel>
-
+    /**
+     * URL
+     */
     private final URL url;
-
+    /**
+     * Dubbo ChannelHandler
+     */
     private final ChannelHandler handler;
 
     public NettyHandler(URL url, ChannelHandler handler) {
@@ -61,13 +68,17 @@ public NettyHandler(URL url, ChannelHandler handler) {
 
     @Override
     public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+        // 创建 NettyChannel 对象
         NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(), url, handler);
         try {
+            // 添加到 `channels` 中
             if (channel != null) {
                 channels.put(NetUtils.toAddressString((InetSocketAddress) ctx.getChannel().getRemoteAddress()), channel);
             }
+            // 提交给 `handler` 处理器。
             handler.connected(channel);
         } finally {
+            // 移除 NettyChannel 对象,若已断开
             NettyChannel.removeChannelIfDisconnected(ctx.getChannel());
         }
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyServer.java b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyServer.java
index c7e77d7e6f..82fc6d3081 100644
--- a/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyServer.java
+++ b/dubbo-remoting/dubbo-remoting-netty/src/main/java/com/alibaba/dubbo/remoting/transport/netty/NettyServer.java
@@ -46,11 +46,16 @@
 
 /**
  * NettyServer
+ *
+ * Netty 服务器实现类
  */
 public class NettyServer extends AbstractServer implements Server {
 
     private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);
 
+    /**
+     * 通道集合
+     */
     private Map<String, Channel> channels; // <ip:port, channel>
 
     private ServerBootstrap bootstrap;
@@ -61,39 +66,52 @@ public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
         super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME)));
     }
 
+    @SuppressWarnings("Duplicates")
     @Override
-    protected void doOpen() throws Throwable {
+    protected void doOpen() {
+        // 设置日志工厂
         NettyHelper.setNettyLoggerFactory();
+
+        // 创建线程池
         ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));
         ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));
+
+        // 创建 ChannelFactory 对象
         ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS));
+        // 实例化 ServerBootstrap
         bootstrap = new ServerBootstrap(channelFactory);
 
+        // 创建 NettyHandler 对象
         final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
+        // 设置 `channels` 属性
         channels = nettyHandler.getChannels();
         // https://issues.jboss.org/browse/NETTY-365
         // https://issues.jboss.org/browse/NETTY-379
         // final Timer timer = new HashedWheelTimer(new NamedThreadFactory("NettyIdleTimer", true));
         bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
+            @Override
             public ChannelPipeline getPipeline() {
+                // 创建 NettyCodecAdapter 对象
                 NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
                 ChannelPipeline pipeline = Channels.pipeline();
                 /*int idleTimeout = getIdleTimeout();
                 if (idleTimeout > 10000) {
                     pipeline.addLast("timer", new IdleStateHandler(timer, idleTimeout / 1000, 0, 0));
                 }*/
-                pipeline.addLast("decoder", adapter.getDecoder());
-                pipeline.addLast("encoder", adapter.getEncoder());
-                pipeline.addLast("handler", nettyHandler);
+                pipeline.addLast("decoder", adapter.getDecoder()); // 解码
+                pipeline.addLast("encoder", adapter.getEncoder()); // 解码
+                pipeline.addLast("handler", nettyHandler); // 处理器
                 return pipeline;
             }
         });
+        // 服务器绑定端口监听
         // bind
         channel = bootstrap.bind(getBindAddress());
     }
 
     @Override
-    protected void doClose() throws Throwable {
+    protected void doClose() {
+        // 关闭服务器通道
         try {
             if (channel != null) {
                 // unbind.
@@ -102,6 +120,7 @@ protected void doClose() throws Throwable {
         } catch (Throwable e) {
             logger.warn(e.getMessage(), e);
         }
+        // 关闭连接到服务器的客户端通道
         try {
             Collection<com.alibaba.dubbo.remoting.Channel> channels = getChannels();
             if (channels != null && !channels.isEmpty()) {
@@ -116,6 +135,7 @@ protected void doClose() throws Throwable {
         } catch (Throwable e) {
             logger.warn(e.getMessage(), e);
         }
+        // 优雅关闭 ServerBootstrap
         try {
             if (bootstrap != null) {
                 // release external resource.
@@ -124,6 +144,7 @@ protected void doClose() throws Throwable {
         } catch (Throwable e) {
             logger.warn(e.getMessage(), e);
         }
+        // 清空连接到服务器的客户端通道
         try {
             if (channels != null) {
                 channels.clear();
@@ -145,10 +166,12 @@ protected void doClose() throws Throwable {
         return chs;
     }
 
+    @Override
     public Channel getChannel(InetSocketAddress remoteAddress) {
         return channels.get(NetUtils.toAddressString(remoteAddress));
     }
 
+    @Override
     public boolean isBound() {
         return channel.isBound();
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyBackedChannelBuffer.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyBackedChannelBuffer.java
index 1748be2050..2cc9b7562f 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyBackedChannelBuffer.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyBackedChannelBuffer.java
@@ -27,6 +27,9 @@
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 
+/**
+ * 基于 Netty ByteBuf 的 ChannelBuffer 实现类
+ */
 public class NettyBackedChannelBuffer implements ChannelBuffer {
 
     private ByteBuf buffer;
@@ -36,37 +39,39 @@ public NettyBackedChannelBuffer(ByteBuf buffer) {
         this.buffer = buffer;
     }
 
-    
+    @Override
     public int capacity() {
         return buffer.capacity();
     }
 
-    
+    @Override
     public ChannelBuffer copy(int index, int length) {
         return new NettyBackedChannelBuffer(buffer.copy(index, length));
     }
 
+    // ByteBuf 的默认最大容量限制是 Integer.MAX_VALUE。
+    @Override
     //has nothing use
     public ChannelBufferFactory factory() {
         return null;
     }
 
-    
+    @Override
     public byte getByte(int index) {
         return buffer.getByte(index);
     }
 
-    
+    @Override
     public void getBytes(int index, byte[] dst, int dstIndex, int length) {
         buffer.getBytes(index, dst, dstIndex, length);
     }
 
-    
+    @Override
     public void getBytes(int index, ByteBuffer dst) {
         buffer.getBytes(index, dst);
     }
 
-    
+    @Override
     public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
         // careful
         byte[] data = new byte[length];
@@ -74,32 +79,32 @@ public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
         dst.setBytes(dstIndex, data, 0, length);
     }
 
-    
+    @Override
     public void getBytes(int index, OutputStream dst, int length) throws IOException {
         buffer.getBytes(index, dst, length);
     }
 
-    
+    @Override
     public boolean isDirect() {
         return buffer.isDirect();
     }
 
-    
+    @Override
     public void setByte(int index, int value) {
         buffer.setByte(index, value);
     }
 
-    
+    @Override
     public void setBytes(int index, byte[] src, int srcIndex, int length) {
         buffer.setBytes(index, src, srcIndex, length);
     }
 
-    
+    @Override
     public void setBytes(int index, ByteBuffer src) {
         buffer.setBytes(index, src);
     }
 
-    
+    @Override
     public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
         // careful
         byte[] data = new byte[length];
@@ -107,27 +112,27 @@ public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
         setBytes(0, data, index, length);
     }
 
-    
+    @Override
     public int setBytes(int index, InputStream src, int length) throws IOException {
         return buffer.setBytes(index, src, length);
     }
 
-    
+    @Override
     public ByteBuffer toByteBuffer(int index, int length) {
         return buffer.nioBuffer(index, length);
     }
 
-    
+    @Override
     public byte[] array() {
         return buffer.array();
     }
 
-    
+    @Override
     public boolean hasArray() {
         return buffer.hasArray();
     }
 
-    
+    @Override
     public int arrayOffset() {
         return buffer.arrayOffset();
     }
@@ -135,39 +140,38 @@ public int arrayOffset() {
 
     // AbstractChannelBuffer
 
-
-    
+    @Override
     public void clear() {
         buffer.clear();
     }
 
-    
+    @Override
     public ChannelBuffer copy() {
         return new NettyBackedChannelBuffer(buffer.copy());
     }
 
-    
+    @Override
     public void discardReadBytes() {
         buffer.discardReadBytes();
     }
 
-    
+    @Override
     public void ensureWritableBytes(int writableBytes) {
         buffer.ensureWritable(writableBytes);
     }
 
-    
+    @Override
     public void getBytes(int index, byte[] dst) {
         buffer.getBytes(index, dst);
     }
 
-    
+    @Override
     public void getBytes(int index, ChannelBuffer dst) {
         // careful
         getBytes(index, dst, dst.writableBytes());
     }
 
-    
+    @Override
     public void getBytes(int index, ChannelBuffer dst, int length) {
         // careful
         if (length > dst.writableBytes()) {
@@ -177,53 +181,53 @@ public void getBytes(int index, ChannelBuffer dst, int length) {
         dst.writerIndex(dst.writerIndex() + length);
     }
 
-    
+    @Override
     public void markReaderIndex() {
         buffer.markReaderIndex();
     }
 
-    
+    @Override
     public void markWriterIndex() {
         buffer.markWriterIndex();
     }
 
-    
+    @Override
     public boolean readable() {
         return buffer.isReadable();
     }
 
-    
+    @Override
     public int readableBytes() {
         return buffer.readableBytes();
     }
 
-    
+    @Override
     public byte readByte() {
         return buffer.readByte();
     }
 
-    
+    @Override
     public void readBytes(byte[] dst) {
         buffer.readBytes(dst);
     }
 
-    
+    @Override
     public void readBytes(byte[] dst, int dstIndex, int length) {
         buffer.readBytes(dst, dstIndex, length);
     }
 
-    
+    @Override
     public void readBytes(ByteBuffer dst) {
         buffer.readBytes(dst);
     }
 
-    
+    @Override
     public void readBytes(ChannelBuffer dst) {
         // careful
         readBytes(dst, dst.writableBytes());
     }
 
-    
+    @Override
     public void readBytes(ChannelBuffer dst, int length) {
         // carefule
         if (length > dst.writableBytes()) {
@@ -233,7 +237,7 @@ public void readBytes(ChannelBuffer dst, int length) {
         dst.writerIndex(dst.writerIndex() + length);
     }
 
-    
+    @Override
     public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
         // careful
         if (readableBytes() < length) {
@@ -244,48 +248,48 @@ public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
         dst.setBytes(dstIndex, data, 0, length);
     }
 
-    
+    @Override
     public ChannelBuffer readBytes(int length) {
         return new NettyBackedChannelBuffer(buffer.readBytes(length));
     }
 
-    
+    @Override
     public void resetReaderIndex() {
         buffer.resetReaderIndex();
     }
 
-    
+    @Override
     public void resetWriterIndex() {
         buffer.resetWriterIndex();
     }
 
-    
+    @Override
     public int readerIndex() {
         return buffer.readerIndex();
     }
 
-    
+    @Override
     public void readerIndex(int readerIndex) {
         buffer.readerIndex(readerIndex);
     }
 
-    
+    @Override
     public void readBytes(OutputStream dst, int length) throws IOException {
         buffer.readBytes(dst, length);
     }
 
-    
+    @Override
     public void setBytes(int index, byte[] src) {
         buffer.setBytes(index, src);
     }
 
-    
+    @Override
     public void setBytes(int index, ChannelBuffer src) {
         // careful
         setBytes(index, src, src.readableBytes());
     }
 
-    
+    @Override
     public void setBytes(int index, ChannelBuffer src, int length) {
         // careful
         if (length > src.readableBytes()) {
@@ -295,58 +299,58 @@ public void setBytes(int index, ChannelBuffer src, int length) {
         src.readerIndex(src.readerIndex() + length);
     }
 
-    
+    @Override
     public void setIndex(int readerIndex, int writerIndex) {
         buffer.setIndex(readerIndex, writerIndex);
     }
 
-    
+    @Override
     public void skipBytes(int length) {
         buffer.skipBytes(length);
     }
 
-    
+    @Override
     public ByteBuffer toByteBuffer() {
         return buffer.nioBuffer();
     }
 
-    
+    @Override
     public boolean writable() {
         return buffer.isWritable();
     }
 
-    
+    @Override
     public int writableBytes() {
         return buffer.writableBytes();
     }
 
-    
+    @Override
     public void writeByte(int value) {
         buffer.writeByte(value);
     }
 
-    
+    @Override
     public void writeBytes(byte[] src) {
         buffer.writeBytes(src);
     }
 
-    
+    @Override
     public void writeBytes(byte[] src, int index, int length) {
         buffer.writeBytes(src, index, length);
     }
 
-    
+    @Override
     public void writeBytes(ByteBuffer src) {
         buffer.writeBytes(src);
     }
 
-    
+    @Override
     public void writeBytes(ChannelBuffer src) {
         // careful
         writeBytes(src, src.readableBytes());
     }
 
-    
+    @Override
     public void writeBytes(ChannelBuffer src, int length) {
         // careful
         if (length > src.readableBytes()) {
@@ -356,7 +360,7 @@ public void writeBytes(ChannelBuffer src, int length) {
         src.readerIndex(src.readerIndex() + length);
     }
 
-    
+    @Override
     public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
         // careful
         byte[] data = new byte[length];
@@ -364,22 +368,22 @@ public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
         writeBytes(data, 0, length);
     }
 
-    
+    @Override
     public int writeBytes(InputStream src, int length) throws IOException {
         return buffer.writeBytes(src, length);
     }
 
-    
+    @Override
     public int writerIndex() {
         return buffer.writerIndex();
     }
 
-    
+    @Override
     public void writerIndex(int writerIndex) {
         buffer.writerIndex(writerIndex);
     }
 
-    
+    @Override
     public int compareTo(ChannelBuffer o) {
         return ChannelBuffers.compare(this, o);
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyChannel.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyChannel.java
index 9cb0bd1154..1f2f25c614 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyChannel.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyChannel.java
@@ -39,13 +39,21 @@
 
     private static final Logger logger = LoggerFactory.getLogger(NettyChannel.class);
 
-    private static final ConcurrentMap<Channel, NettyChannel> channelMap = new ConcurrentHashMap<Channel, NettyChannel>();
-
-    private final Channel channel;
-
+    /**
+     * 通道集合
+     */
+    private static final ConcurrentMap<io.netty.channel.Channel, NettyChannel> channelMap = new ConcurrentHashMap<Channel, NettyChannel>();
+
+    /**
+     * 通道
+     */
+    private final io.netty.channel.Channel channel;
+    /**
+     * 属性集合
+     */
     private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
 
-    private NettyChannel(Channel channel, URL url, ChannelHandler handler) {
+    private NettyChannel(io.netty.channel.Channel channel, URL url, ChannelHandler handler) {
         super(url, handler);
         if (channel == null) {
             throw new IllegalArgumentException("netty channel == null;");
@@ -53,15 +61,23 @@ private NettyChannel(Channel channel, URL url, ChannelHandler handler) {
         this.channel = channel;
     }
 
-    static NettyChannel getOrAddChannel(Channel ch, URL url, ChannelHandler handler) {
+    /**
+     * 创建 NettyChannel 对象
+     *
+     * @param ch 通道
+     * @param url URL
+     * @param handler 处理器
+     * @return NettyChannel 对象
+     */
+    static NettyChannel getOrAddChannel(io.netty.channel.Channel ch, URL url, ChannelHandler handler) {
         if (ch == null) {
             return null;
         }
         NettyChannel ret = channelMap.get(ch);
         if (ret == null) {
             NettyChannel nettyChannel = new NettyChannel(ch, url, handler);
-            if (ch.isActive()) {
-                ret = channelMap.putIfAbsent(ch, nettyChannel);
+            if (ch.isActive()) { // 连接中
+                ret = channelMap.putIfAbsent(ch, nettyChannel); // 添加到 channelMap
             }
             if (ret == null) {
                 ret = nettyChannel;
@@ -70,35 +86,48 @@ static NettyChannel getOrAddChannel(Channel ch, URL url, ChannelHandler handler)
         return ret;
     }
 
-    static void removeChannelIfDisconnected(Channel ch) {
-        if (ch != null && !ch.isActive()) {
-            channelMap.remove(ch);
+    /**
+     * 移除 NettyChannel 对象
+     *
+     * @param ch 通道
+     */
+    static void removeChannelIfDisconnected(io.netty.channel.Channel ch) {
+        if (ch != null && !ch.isActive()) { // 未连接
+            channelMap.remove(ch); // 移除出channelMap
         }
     }
 
+    @Override
     public InetSocketAddress getLocalAddress() {
         return (InetSocketAddress) channel.localAddress();
     }
 
+    @Override
     public InetSocketAddress getRemoteAddress() {
         return (InetSocketAddress) channel.remoteAddress();
     }
 
+    @Override
     public boolean isConnected() {
         return !isClosed() && channel.isActive();
     }
 
+    @Override
     public void send(Object message, boolean sent) throws RemotingException {
+        // 检查连接状态
         super.send(message, sent);
 
-        boolean success = true;
+        boolean success = true; // 如果没有等待发送成功,默认成功。
         int timeout = 0;
         try {
+            // 发送消息
             ChannelFuture future = channel.writeAndFlush(message);
+            // 等待发送成功
             if (sent) {
                 timeout = getUrl().getPositiveParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
                 success = future.await(timeout);
             }
+            // 若发生异常,抛出
             Throwable cause = future.cause();
             if (cause != null) {
                 throw cause;
@@ -107,28 +136,35 @@ public void send(Object message, boolean sent) throws RemotingException {
             throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e);
         }
 
+        // 发送失败,抛出异常
         if (!success) {
             throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress()
                     + "in timeout(" + timeout + "ms) limit");
         }
     }
 
+    @Override
+    @SuppressWarnings("Duplicates")
     public void close() {
+        // 标记关闭
         try {
             super.close();
         } catch (Exception e) {
             logger.warn(e.getMessage(), e);
         }
+        // 移除连接
         try {
             removeChannelIfDisconnected(channel);
         } catch (Exception e) {
             logger.warn(e.getMessage(), e);
         }
+        // 清空属性 attributes
         try {
             attributes.clear();
         } catch (Exception e) {
             logger.warn(e.getMessage(), e);
         }
+        // 关闭真正的通道 channel
         try {
             if (logger.isInfoEnabled()) {
                 logger.info("Close netty channel " + channel);
@@ -139,14 +175,17 @@ public void close() {
         }
     }
 
+    @Override
     public boolean hasAttribute(String key) {
         return attributes.containsKey(key);
     }
 
+    @Override
     public Object getAttribute(String key) {
         return attributes.get(key);
     }
 
+    @Override
     public void setAttribute(String key, Object value) {
         if (value == null) { // The null value unallowed in the ConcurrentHashMap.
             attributes.remove(key);
@@ -155,6 +194,7 @@ public void setAttribute(String key, Object value) {
         }
     }
 
+    @Override
     public void removeAttribute(String key) {
         attributes.remove(key);
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClient.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClient.java
index d356bc8f21..3afa054642 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClient.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClient.java
@@ -46,55 +46,73 @@
 
     private static final Logger logger = LoggerFactory.getLogger(NettyClient.class);
 
+    // 【TODO 8027】为啥公用
     private static final NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(Constants.DEFAULT_IO_THREADS, new DefaultThreadFactory("NettyClientWorker", true));
 
     private Bootstrap bootstrap;
 
-    private volatile Channel channel; // volatile, please copy reference to use
+    private volatile io.netty.channel.Channel channel; // volatile, please copy reference to use
 
     public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException {
         super(url, wrapChannelHandler(url, handler));
     }
 
     @Override
-    protected void doOpen() throws Throwable {
+    protected void doOpen() {
+        // 设置日志工厂
         NettyHelper.setNettyLoggerFactory();
+
+        // 创建 NettyClientHandler 对象
         final NettyClientHandler nettyClientHandler = new NettyClientHandler(getUrl(), this);
+
+        // 实例化 ServerBootstrap
         bootstrap = new Bootstrap();
-        bootstrap.group(nioEventLoopGroup)
+        bootstrap
+                // 设置它的线程组
+                .group(nioEventLoopGroup)
+                // 设置可选项
                 .option(ChannelOption.SO_KEEPALIVE, true)
                 .option(ChannelOption.TCP_NODELAY, true)
                 .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                 //.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getTimeout())
+                // 设置 Channel类型
                 .channel(NioSocketChannel.class);
 
+        // 设置连接超时时间
         if (getTimeout() < 3000) {
             bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000);
         } else {
             bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getTimeout());
         }
 
+        // 设置责任链路
         bootstrap.handler(new ChannelInitializer() {
-
-            protected void initChannel(Channel ch) throws Exception {
+            @Override
+            protected void initChannel(Channel ch) {
+                // 创建 NettyCodecAdapter 对象
                 NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this);
                 ch.pipeline()//.addLast("logging",new LoggingHandler(LogLevel.INFO))//for debug
-                        .addLast("decoder", adapter.getDecoder())
-                        .addLast("encoder", adapter.getEncoder())
-                        .addLast("handler", nettyClientHandler);
+                        .addLast("decoder", adapter.getDecoder()) // 解码
+                        .addLast("encoder", adapter.getEncoder()) // 编码
+                        .addLast("handler", nettyClientHandler); // 处理器
             }
         });
     }
 
+    @Override
+    @SuppressWarnings("Duplicates")
     protected void doConnect() throws Throwable {
         long start = System.currentTimeMillis();
+        // 连接服务器
         ChannelFuture future = bootstrap.connect(getConnectAddress());
         try {
+            // 等待连接成功或者超时
             boolean ret = future.awaitUninterruptibly(3000, TimeUnit.MILLISECONDS);
-
+            // 连接成功
             if (ret && future.isSuccess()) {
                 Channel newChannel = future.channel();
                 try {
+                    // 关闭老的连接
                     // Close old channel
                     Channel oldChannel = NettyClient.this.channel; // copy reference
                     if (oldChannel != null) {
@@ -108,6 +126,7 @@ protected void doConnect() throws Throwable {
                         }
                     }
                 } finally {
+                    // 若 NettyClient 被关闭,关闭连接
                     if (NettyClient.this.isClosed()) {
                         try {
                             if (logger.isInfoEnabled()) {
@@ -118,13 +137,16 @@ protected void doConnect() throws Throwable {
                             NettyClient.this.channel = null;
                             NettyChannel.removeChannelIfDisconnected(newChannel);
                         }
+                    // 设置新连接
                     } else {
                         NettyClient.this.channel = newChannel;
                     }
                 }
+            // 发生异常,抛出 RemotingException 异常
             } else if (future.cause() != null) {
                 throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
                         + getRemoteAddress() + ", error message is:" + future.cause().getMessage(), future.cause());
+            // 无结果(连接超时),抛出 RemotingException 异常
             } else {
                 throw new RemotingException(this, "client(url: " + getUrl() + ") failed to connect to server "
                         + getRemoteAddress() + " client-side timeout "
@@ -132,14 +154,14 @@ protected void doConnect() throws Throwable {
                         + NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion());
             }
         } finally {
-            if (!isConnected()) {
+            if (!isConnected()) { // 【TODO 8028】为什么不取消 future
                 //future.cancel(true);
             }
         }
     }
 
     @Override
-    protected void doDisConnect() throws Throwable {
+    protected void doDisConnect() {
         try {
             NettyChannel.removeChannelIfDisconnected(channel);
         } catch (Throwable t) {
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClientHandler.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClientHandler.java
index f75d7028dd..221187ce88 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClientHandler.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClientHandler.java
@@ -29,8 +29,13 @@
 @io.netty.channel.ChannelHandler.Sharable
 public class NettyClientHandler extends ChannelDuplexHandler {
 
+    /**
+     * Dubbo URL
+     */
     private final URL url;
-
+    /**
+     * Dubbo ChannelHandler
+     */
     private final ChannelHandler handler;
 
     public NettyClientHandler(URL url, ChannelHandler handler) {
@@ -44,14 +49,13 @@ public NettyClientHandler(URL url, ChannelHandler handler) {
         this.handler = handler;
     }
 
-
     @Override
-    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+    public void channelActive(ChannelHandlerContext ctx) {
         ctx.fireChannelActive();
     }
 
     @Override
-    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+    public void channelInactive(ChannelHandlerContext ctx) {
         ctx.fireChannelInactive();
     }
 
@@ -76,7 +80,6 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
         }
     }
 
-
     @Override
     public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
         super.write(ctx, msg, promise);
@@ -98,4 +101,5 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
             NettyChannel.removeChannelIfDisconnected(ctx.channel());
         }
     }
+
 }
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyCodecAdapter.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyCodecAdapter.java
index dc15705c30..27d6187ffa 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyCodecAdapter.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyCodecAdapter.java
@@ -35,14 +35,26 @@
  */
 final class NettyCodecAdapter {
 
+    /**
+     * Netty 编码器
+     */
     private final ChannelHandler encoder = new InternalEncoder();
-
+    /**
+     * Netty 解码器
+     */
     private final ChannelHandler decoder = new InternalDecoder();
 
+    /**
+     * Dubbo 编解码器
+     */
     private final Codec2 codec;
-
+    /**
+     * Dubbo URL
+     */
     private final URL url;
-
+    /**
+     * Dubbo ChannelHandler
+     */
     private final com.alibaba.dubbo.remoting.ChannelHandler handler;
 
     public NettyCodecAdapter(Codec2 codec, URL url, com.alibaba.dubbo.remoting.ChannelHandler handler) {
@@ -61,44 +73,53 @@ public ChannelHandler getDecoder() {
 
     private class InternalEncoder extends MessageToByteEncoder {
 
+        @Override
         protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
+            // 创建 NettyBackedChannelBuffer 对象
             com.alibaba.dubbo.remoting.buffer.ChannelBuffer buffer = new NettyBackedChannelBuffer(out);
+            // 获得 NettyChannel 对象
             Channel ch = ctx.channel();
             NettyChannel channel = NettyChannel.getOrAddChannel(ch, url, handler);
             try {
+                // 编码
                 codec.encode(channel, buffer, msg);
             } finally {
+                // 移除 NettyChannel 对象,若断开连接
                 NettyChannel.removeChannelIfDisconnected(ch);
             }
         }
+
     }
 
     private class InternalDecoder extends ByteToMessageDecoder {
 
+        @Override
         protected void decode(ChannelHandlerContext ctx, ByteBuf input, List<Object> out) throws Exception {
-
+            // 创建 NettyBackedChannelBuffer 对象
             ChannelBuffer message = new NettyBackedChannelBuffer(input);
-
+            // 获得 NettyChannel 对象
             NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
-
+            // 循环解析,直到结束
             Object msg;
-
             int saveReaderIndex;
-
             try {
                 // decode object.
                 do {
+                    // 记录当前读进度
                     saveReaderIndex = message.readerIndex();
+                    // 解码
                     try {
                         msg = codec.decode(channel, message);
                     } catch (IOException e) {
                         throw e;
                     }
+                    // 需要更多输入,即消息不完整,标记回原有读进度,并结束
                     if (msg == Codec2.DecodeResult.NEED_MORE_INPUT) {
                         message.readerIndex(saveReaderIndex);
                         break;
+                    // 解码到消息,添加到 `out`
                     } else {
-                        //is it possible to go here ?
+                        //is it possible to go here ? 芋艿:不可能,哈哈哈
                         if (saveReaderIndex == message.readerIndex()) {
                             throw new IOException("Decode without read data.");
                         }
@@ -108,6 +129,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf input, List<Object> out
                     }
                 } while (message.readable());
             } finally {
+                // 移除 NettyChannel 对象,若断开连接
                 NettyChannel.removeChannelIfDisconnected(ctx.channel());
             }
         }
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyServer.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyServer.java
index ef70c2d902..6dc2a6e66c 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyServer.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyServer.java
@@ -48,11 +48,16 @@
 
 /**
  * NettyServer
+ *
+ * Netty 服务器实现类
  */
 public class NettyServer extends AbstractServer implements Server {
 
     private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);
 
+    /**
+     * 通道集合
+     */
     private Map<String, Channel> channels; // <ip:port, channel>
 
     private ServerBootstrap bootstrap;
@@ -63,46 +68,59 @@
     private EventLoopGroup workerGroup;
 
     public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
-        super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME)));
+        super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME) /* 设置线程名到 URL 上 */));
     }
 
     @Override
-    protected void doOpen() throws Throwable {
+    protected void doOpen() {
+        // 设置日志工厂
         NettyHelper.setNettyLoggerFactory();
 
+        // 实例化 ServerBootstrap
         bootstrap = new ServerBootstrap();
 
+        // 创建线程组
         bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("NettyServerBoss", true));
         workerGroup = new NioEventLoopGroup(getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS),
                 new DefaultThreadFactory("NettyServerWorker", true));
 
+        // 创建 NettyServerHandler 对象
         final NettyServerHandler nettyServerHandler = new NettyServerHandler(getUrl(), this);
+        // 设置 `channels` 属性
         channels = nettyServerHandler.getChannels();
 
-        bootstrap.group(bossGroup, workerGroup)
-                .channel(NioServerSocketChannel.class)
+        bootstrap
+                // 设置它的线程组
+                .group(bossGroup, workerGroup)
+                // 设置 Channel类型
+                .channel(NioServerSocketChannel.class) // Server
+                // 设置可选项
                 .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE)
                 .childOption(ChannelOption.SO_REUSEADDR, Boolean.TRUE)
                 .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
+                // 设置责任链路
                 .childHandler(new ChannelInitializer<NioSocketChannel>() {
                     @Override
-                    protected void initChannel(NioSocketChannel ch) throws Exception {
+                    protected void initChannel(NioSocketChannel ch) {
+                        // 创建 NettyCodecAdapter 对象
                         NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
                         ch.pipeline()//.addLast("logging",new LoggingHandler(LogLevel.INFO))//for debug
-                                .addLast("decoder", adapter.getDecoder())
-                                .addLast("encoder", adapter.getEncoder())
-                                .addLast("handler", nettyServerHandler);
+                                .addLast("decoder", adapter.getDecoder()) // 解码
+                                .addLast("encoder", adapter.getEncoder())  // 解码
+                                .addLast("handler", nettyServerHandler); // 处理器
                     }
                 });
+
+        // 服务器绑定端口监听
         // bind
         ChannelFuture channelFuture = bootstrap.bind(getBindAddress());
         channelFuture.syncUninterruptibly();
         channel = channelFuture.channel();
-
     }
 
     @Override
-    protected void doClose() throws Throwable {
+    protected void doClose() {
+        // 关闭服务器通道
         try {
             if (channel != null) {
                 // unbind.
@@ -111,6 +129,7 @@ protected void doClose() throws Throwable {
         } catch (Throwable e) {
             logger.warn(e.getMessage(), e);
         }
+        // 关闭连接到服务器的客户端通道
         try {
             Collection<com.alibaba.dubbo.remoting.Channel> channels = getChannels();
             if (channels != null && channels.size() > 0) {
@@ -125,6 +144,7 @@ protected void doClose() throws Throwable {
         } catch (Throwable e) {
             logger.warn(e.getMessage(), e);
         }
+        // 优雅关闭工作组
         try {
             if (bootstrap != null) {
                 bossGroup.shutdownGracefully();
@@ -133,6 +153,7 @@ protected void doClose() throws Throwable {
         } catch (Throwable e) {
             logger.warn(e.getMessage(), e);
         }
+        // 清空连接到服务器的客户端通道
         try {
             if (channels != null) {
                 channels.clear();
@@ -142,22 +163,27 @@ protected void doClose() throws Throwable {
         }
     }
 
+    /**
+     * @return 通道数组
+     */
     public Collection<Channel> getChannels() {
         Collection<Channel> chs = new HashSet<Channel>();
         for (Channel channel : this.channels.values()) {
-            if (channel.isConnected()) {
+            if (channel.isConnected()) { // 已连接,返回
                 chs.add(channel);
-            } else {
+            } else { // 未连接,移除
                 channels.remove(NetUtils.toAddressString(channel.getRemoteAddress()));
             }
         }
         return chs;
     }
 
+    @Override
     public Channel getChannel(InetSocketAddress remoteAddress) {
         return channels.get(NetUtils.toAddressString(remoteAddress));
     }
 
+    @Override
     public boolean isBound() {
         return channel.isActive();
     }
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyServerHandler.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyServerHandler.java
index e23a500c26..b4dd7bc17a 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyServerHandler.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyServerHandler.java
@@ -30,15 +30,22 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * NettyClientHandler
+ * NettyServerHandler
  */
 @io.netty.channel.ChannelHandler.Sharable
 public class NettyServerHandler extends ChannelDuplexHandler {
 
+    /**
+     * Dubbo Channel 集合
+     */
     private final Map<String, Channel> channels = new ConcurrentHashMap<String, Channel>(); // <ip:port, channel>
-
+    /**
+     * URL
+     */
     private final URL url;
-
+    /**
+     * Dubbo ChannelHandler
+     */
     private final ChannelHandler handler;
 
     public NettyServerHandler(URL url, ChannelHandler handler) {
@@ -58,15 +65,21 @@ public NettyServerHandler(URL url, ChannelHandler handler) {
 
     @Override
     public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        // 交给下一个节点处理
+        // 芋艿:实际此处不要调用也没关系,因为 NettyServerHandler 没下一个节点。
         ctx.fireChannelActive();
 
+        // 创建 NettyChannel 对象
         NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
         try {
+            // 添加到 `channels` 中
             if (channel != null) {
                 channels.put(NetUtils.toAddressString((InetSocketAddress) ctx.channel().remoteAddress()), channel);
             }
+            // 提交给 `handler` 处理器。
             handler.connected(channel);
         } finally {
+            // 移除 NettyChannel 对象,若已断开
             NettyChannel.removeChannelIfDisconnected(ctx.channel());
         }
     }
@@ -82,11 +95,9 @@ public void channelInactive(ChannelHandlerContext ctx) throws Exception {
         }
     }
 
-
     @Override
-    public void disconnect(ChannelHandlerContext ctx, ChannelPromise future)
-            throws Exception {
-
+    public void disconnect(ChannelHandlerContext ctx, ChannelPromise future) {
+        // 因为没有请求从远端断开 Channel
     }
 
     @Override
@@ -99,12 +110,13 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
         }
     }
 
-
     @Override
     public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
+        // 发送消息
         super.write(ctx, msg, promise);
         NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
         try {
+            // 提交给 `handler` 处理器。
             handler.sent(channel, msg);
         } finally {
             NettyChannel.removeChannelIfDisconnected(ctx.channel());
@@ -121,4 +133,5 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
             NettyChannel.removeChannelIfDisconnected(ctx.channel());
         }
     }
+
 }
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyTransporter.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyTransporter.java
index 4a4ac209bd..8c094c554b 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyTransporter.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/NettyTransporter.java
@@ -23,8 +23,14 @@
 import com.alibaba.dubbo.remoting.Server;
 import com.alibaba.dubbo.remoting.Transporter;
 
+/**
+ * 基于 Netty4 的网络传输实现类
+ */
 public class NettyTransporter implements Transporter {
 
+    /**
+     * 拓展名
+     */
     public static final String NAME = "netty4";
 
     public Server bind(URL url, ChannelHandler listener) throws RemotingException {
@@ -35,4 +41,4 @@ public Client connect(URL url, ChannelHandler listener) throws RemotingException
         return new NettyClient(url, listener);
     }
 
-}
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/FormattingTuple.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/FormattingTuple.java
index a4d086ecdb..ff84f923ea 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/FormattingTuple.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/FormattingTuple.java
@@ -19,13 +19,24 @@
 
 /**
  * Holds the results of formatting done by {@link MessageFormatter}.
+ *
+ * 从 {@link io.netty.util.internal.logging.MessageFormatter} 复制
  */
 class FormattingTuple {
 
     static final FormattingTuple NULL = new FormattingTuple(null);
 
+    /**
+     * 消息
+     */
     private final String message;
+    /**
+     * 异常
+     */
     private final Throwable throwable;
+    /**
+     * 参数数组
+     */
     private final Object[] argArray;
 
     FormattingTuple(String message) {
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/MessageFormatter.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/MessageFormatter.java
index 5ccf3f38bc..b998083433 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/MessageFormatter.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/MessageFormatter.java
@@ -85,6 +85,8 @@
  * See also {@link #format(String, Object)},
  * {@link #format(String, Object, Object)} and
  * {@link #arrayFormat(String, Object[])} methods for more details.
+ *
+ * 从 {@link io.netty.util.internal.logging.MessageFormatter} 复制
  */
 final class MessageFormatter {
     static final char DELIM_START = '{';
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/NettyHelper.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/NettyHelper.java
index 7b54636fdd..38675b2e3b 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/NettyHelper.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/com/alibaba/dubbo/remoting/transport/netty4/logging/NettyHelper.java
@@ -24,6 +24,9 @@
 
 public class NettyHelper {
 
+    /**
+     * 设置日志工厂,基于 Dubbo Logger 组件。
+     */
     public static void setNettyLoggerFactory() {
         InternalLoggerFactory factory = InternalLoggerFactory.getDefaultFactory();
         if (factory == null || !(factory instanceof DubboLoggerFactory)) {
@@ -37,27 +40,34 @@ public static void setNettyLoggerFactory() {
         public InternalLogger newInstance(String name) {
             return new DubboLogger(LoggerFactory.getLogger(name));
         }
+
     }
 
     static class DubboLogger extends AbstractInternalLogger {
 
-        private Logger logger;
+        /**
+         * 日志组件
+         */
+        private com.alibaba.dubbo.common.logger.Logger logger;
 
         DubboLogger(Logger logger) {
             super(logger.getClass().getName());
             this.logger = logger;
         }
 
+        @Override
         public boolean isTraceEnabled() {
             return logger.isTraceEnabled();
         }
 
+        @Override
         public void trace(String msg) {
             if (isTraceEnabled()) {
                 logger.trace(msg);
             }
         }
 
+        @Override
         public void trace(String format, Object arg) {
             if (isTraceEnabled()) {
                 FormattingTuple ft = MessageFormatter.format(format, arg);
@@ -66,6 +76,7 @@ public void trace(String format, Object arg) {
 
         }
 
+        @Override
         public void trace(String format, Object argA, Object argB) {
             if (isTraceEnabled()) {
                 FormattingTuple ft = MessageFormatter.format(format, argA, argB);
@@ -73,6 +84,7 @@ public void trace(String format, Object argA, Object argB) {
             }
         }
 
+        @Override
         public void trace(String format, Object... arguments) {
             if (isTraceEnabled()) {
                 FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments);
@@ -80,22 +92,26 @@ public void trace(String format, Object... arguments) {
             }
         }
 
+        @Override
         public void trace(String msg, Throwable t) {
             if (isTraceEnabled()) {
                 logger.trace(msg, t);
             }
         }
 
+        @Override
         public boolean isDebugEnabled() {
             return logger.isDebugEnabled();
         }
 
+        @Override
         public void debug(String msg) {
             if (isDebugEnabled()) {
                 logger.debug(msg);
             }
         }
 
+        @Override
         public void debug(String format, Object arg) {
             if (isDebugEnabled()) {
                 FormattingTuple ft = MessageFormatter.format(format, arg);
@@ -103,6 +119,7 @@ public void debug(String format, Object arg) {
             }
         }
 
+        @Override
         public void debug(String format, Object argA, Object argB) {
             if (isDebugEnabled()) {
                 FormattingTuple ft = MessageFormatter.format(format, argA, argB);
@@ -110,6 +127,7 @@ public void debug(String format, Object argA, Object argB) {
             }
         }
 
+        @Override
         public void debug(String format, Object... arguments) {
             if (isDebugEnabled()) {
                 FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments);
@@ -117,22 +135,26 @@ public void debug(String format, Object... arguments) {
             }
         }
 
+        @Override
         public void debug(String msg, Throwable t) {
             if (isDebugEnabled()) {
                 logger.debug(msg, t);
             }
         }
 
+        @Override
         public boolean isInfoEnabled() {
             return logger.isInfoEnabled();
         }
 
+        @Override
         public void info(String msg) {
             if (isInfoEnabled()) {
                 logger.info(msg);
             }
         }
 
+        @Override
         public void info(String format, Object arg) {
             if (isInfoEnabled()) {
                 FormattingTuple ft = MessageFormatter.format(format, arg);
@@ -140,6 +162,7 @@ public void info(String format, Object arg) {
             }
         }
 
+        @Override
         public void info(String format, Object argA, Object argB) {
             if (isInfoEnabled()) {
                 FormattingTuple ft = MessageFormatter.format(format, argA, argB);
@@ -147,6 +170,7 @@ public void info(String format, Object argA, Object argB) {
             }
         }
 
+        @Override
         public void info(String format, Object... arguments) {
             if (isInfoEnabled()) {
                 FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments);
@@ -154,22 +178,26 @@ public void info(String format, Object... arguments) {
             }
         }
 
+        @Override
         public void info(String msg, Throwable t) {
             if (isInfoEnabled()) {
                 logger.info(msg, t);
             }
         }
 
+        @Override
         public boolean isWarnEnabled() {
             return false;
         }
 
+        @Override
         public void warn(String msg) {
             if (isWarnEnabled()) {
                 logger.warn(msg);
             }
         }
 
+        @Override
         public void warn(String format, Object arg) {
             if (isWarnEnabled()) {
                 FormattingTuple ft = MessageFormatter.format(format, arg);
@@ -177,6 +205,7 @@ public void warn(String format, Object arg) {
             }
         }
 
+        @Override
         public void warn(String format, Object... arguments) {
             if (isWarnEnabled()) {
                 FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments);
@@ -184,6 +213,7 @@ public void warn(String format, Object... arguments) {
             }
         }
 
+        @Override
         public void warn(String format, Object argA, Object argB) {
             if (isWarnEnabled()) {
                 FormattingTuple ft = MessageFormatter.format(format, argA, argB);
@@ -191,22 +221,26 @@ public void warn(String format, Object argA, Object argB) {
             }
         }
 
+        @Override
         public void warn(String msg, Throwable t) {
             if (isWarnEnabled()) {
                 logger.warn(msg, t);
             }
         }
 
+        @Override
         public boolean isErrorEnabled() {
             return logger.isErrorEnabled();
         }
 
+        @Override
         public void error(String msg) {
             if (isErrorEnabled()) {
                 logger.error(msg);
             }
         }
 
+        @Override
         public void error(String format, Object arg) {
             if (isErrorEnabled()) {
                 FormattingTuple ft = MessageFormatter.format(format, arg);
@@ -214,6 +248,7 @@ public void error(String format, Object arg) {
             }
         }
 
+        @Override
         public void error(String format, Object argA, Object argB) {
             if (isErrorEnabled()) {
                 FormattingTuple ft = MessageFormatter.format(format, argA, argB);
@@ -221,6 +256,7 @@ public void error(String format, Object argA, Object argB) {
             }
         }
 
+        @Override
         public void error(String format, Object... arguments) {
             if (isErrorEnabled()) {
                 FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments);
@@ -228,6 +264,7 @@ public void error(String format, Object... arguments) {
             }
         }
 
+        @Override
         public void error(String msg, Throwable t) {
             if (isErrorEnabled()) {
                 logger.error(msg, t);
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ChildListener.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ChildListener.java
index e213a8afb1..66cdcb4535 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ChildListener.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ChildListener.java
@@ -18,8 +18,17 @@
 
 import java.util.List;
 
+/**
+ * 节点监听器接口
+ */
 public interface ChildListener {
 
+    /**
+     * 子节点发生变化的回调
+     *
+     * @param path 节点
+     * @param children 最新的子节点列表
+     */
     void childChanged(String path, List<String> children);
 
-}
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/StateListener.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/StateListener.java
index 7b9f03686d..94374310b8 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/StateListener.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/StateListener.java
@@ -16,14 +16,29 @@
  */
 package com.alibaba.dubbo.remoting.zookeeper;
 
+/**
+ * 状态监听器接口
+ */
 public interface StateListener {
 
+    /**
+     * 状态 - 已断开
+     */
     int DISCONNECTED = 0;
-
+    /**
+     * 状态 - 已连接
+     */
     int CONNECTED = 1;
-
+    /**
+     * 状态 - 已重连
+     */
     int RECONNECTED = 2;
 
+    /**
+     * 状态变更回调
+     *
+     * @param connected 状态
+     */
     void stateChanged(int connected);
 
-}
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ZookeeperClient.java
index f4132a2a54..b44501dd29 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ZookeeperClient.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ZookeeperClient.java
@@ -20,26 +20,72 @@
 
 import java.util.List;
 
+/**
+ * Zookeeper 客户端接口
+ */
 public interface ZookeeperClient {
 
+    /**
+     * 创建节点
+     *
+     * @param path 节点路径
+     * @param ephemeral 是否临时节点
+     */
     void create(String path, boolean ephemeral);
 
+    /**
+     * 删除节点
+     *
+     * @param path 节点路径
+     */
     void delete(String path);
 
     List<String> getChildren(String path);
 
+    /**
+     * 添加 ChildListener
+     *
+     * @param path 节点路径
+     * @param listener 监听器
+     * @return 子节点列表
+     */
     List<String> addChildListener(String path, ChildListener listener);
 
+    /**
+     * 移除 ChildListener
+     *
+     * @param path 节点路径
+     * @param listener 监听器
+     */
     void removeChildListener(String path, ChildListener listener);
 
+    /**
+     * 添加 StateListener
+     *
+     * @param listener 监听器
+     */
     void addStateListener(StateListener listener);
 
+    /**
+     * 移除 StateListener
+     *
+     * @param listener 监听器
+     */
     void removeStateListener(StateListener listener);
 
+    /**
+     * @return 是否连接
+     */
     boolean isConnected();
 
+    /**
+     * 关闭
+     */
     void close();
 
+    /**
+     * @return 获得注册中心 URL
+     */
     URL getUrl();
 
 }
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ZookeeperTransporter.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ZookeeperTransporter.java
index bbddd8ceea..64f66f07bd 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ZookeeperTransporter.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/ZookeeperTransporter.java
@@ -21,9 +21,18 @@
 import com.alibaba.dubbo.common.extension.Adaptive;
 import com.alibaba.dubbo.common.extension.SPI;
 
+/**
+ * Zookeeper 工厂接口
+ */
 @SPI("curator")
 public interface ZookeeperTransporter {
 
+    /**
+     * 连接创建 ZookeeperClient 对象
+     *
+     * @param url 注册中心地址
+     * @return ZookeeperClient 对象
+     */
     @Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})
     ZookeeperClient connect(URL url);
 
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java
index 33ddf43d24..84d1e6793c 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java
@@ -36,22 +36,30 @@
 import java.util.Collections;
 import java.util.List;
 
+/**
+ * 基于 Curator 的 Zookeeper 客户端实现类
+ */
 public class CuratorZookeeperClient extends AbstractZookeeperClient<CuratorWatcher> {
 
+    /**
+     * client 对象
+     */
     private final CuratorFramework client;
 
     public CuratorZookeeperClient(URL url) {
         super(url);
         try {
+            // 创建 client 对象
             CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
-                    .connectString(url.getBackupAddress())
-                    .retryPolicy(new RetryNTimes(1, 1000))
-                    .connectionTimeoutMs(5000);
+                    .connectString(url.getBackupAddress()) // 连接地址
+                    .retryPolicy(new RetryNTimes(1, 1000)) // 重试策略,1 次,间隔 1000 ms
+                    .connectionTimeoutMs(5000); // 连接超时时间
             String authority = url.getAuthority();
             if (authority != null && authority.length() > 0) {
                 builder = builder.authorization("digest", authority.getBytes());
             }
             client = builder.build();
+            // 添加连接监听器
             client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
                 public void stateChanged(CuratorFramework client, ConnectionState state) {
                     if (state == ConnectionState.LOST) {
@@ -63,6 +71,7 @@ public void stateChanged(CuratorFramework client, ConnectionState state) {
                     }
                 }
             });
+            // 启动 client
             client.start();
         } catch (Exception e) {
             throw new IllegalStateException(e.getMessage(), e);
@@ -72,7 +81,7 @@ public void stateChanged(CuratorFramework client, ConnectionState state) {
     public void createPersistent(String path) {
         try {
             client.create().forPath(path);
-        } catch (NodeExistsException e) {
+        } catch (NodeExistsException e) { // 忽略异常
         } catch (Exception e) {
             throw new IllegalStateException(e.getMessage(), e);
         }
@@ -81,12 +90,13 @@ public void createPersistent(String path) {
     public void createEphemeral(String path) {
         try {
             client.create().withMode(CreateMode.EPHEMERAL).forPath(path);
-        } catch (NodeExistsException e) {
+        } catch (NodeExistsException e) { // 忽略异常
         } catch (Exception e) {
             throw new IllegalStateException(e.getMessage(), e);
         }
     }
 
+    @Override
     public void delete(String path) {
         try {
             client.delete().forPath(path);
@@ -96,6 +106,7 @@ public void delete(String path) {
         }
     }
 
+    @Override
     public List<String> getChildren(String path) {
         try {
             return client.getChildren().forPath(path);
@@ -111,10 +122,12 @@ public boolean checkExists(String path) {
             if (client.checkExists().forPath(path) != null) {
                 return true;
             }
-        } catch (Exception e) {
+        } catch (Exception e) { // 忽略异常
         }
         return false;
     }
+
+    @Override
     public boolean isConnected() {
         return client.getZookeeperClient().isConnected();
     }
@@ -153,6 +166,7 @@ public void unwatch() {
             this.listener = null;
         }
 
+        @Override
         public void process(WatchedEvent event) throws Exception {
             if (listener != null) {
                 String path = event.getPath() == null ? "" : event.getPath();
@@ -161,8 +175,8 @@ public void process(WatchedEvent event) throws Exception {
                         // if client connect or disconnect to server, zookeeper will queue
                         // watched event(Watcher.Event.EventType.None, .., path = null).
                         StringUtils.isNotEmpty(path)
-                                ? client.getChildren().usingWatcher(this).forPath(path)
-                                : Collections.<String>emptyList());
+                                ? client.getChildren().usingWatcher(this).forPath(path) // 重新发起连接,并传入最新的子节点列表
+                                : Collections.<String>emptyList()); //
             }
         }
     }
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/curator/CuratorZookeeperTransporter.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/curator/CuratorZookeeperTransporter.java
index db07ed9192..c49aac978b 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/curator/CuratorZookeeperTransporter.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/curator/CuratorZookeeperTransporter.java
@@ -20,6 +20,9 @@
 import com.alibaba.dubbo.remoting.zookeeper.ZookeeperClient;
 import com.alibaba.dubbo.remoting.zookeeper.ZookeeperTransporter;
 
+/**
+ * CuratorZookeeper 工厂实现类
+ */
 public class CuratorZookeeperTransporter implements ZookeeperTransporter {
 
     public ZookeeperClient connect(URL url) {
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java
index 0b4070adca..e536020907 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java
@@ -29,27 +29,48 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArraySet;
 
+/**
+ * Zookeeper 客户端抽象类
+ *
+ * @param <TargetChildListener> 监听器具体对象类
+ */
 public abstract class AbstractZookeeperClient<TargetChildListener> implements ZookeeperClient {
 
     protected static final Logger logger = LoggerFactory.getLogger(AbstractZookeeperClient.class);
 
+    /**
+     * 注册中心 URL
+     */
     private final URL url;
-
+    /**
+     * StateListener 集合
+     */
     private final Set<StateListener> stateListeners = new CopyOnWriteArraySet<StateListener>();
-
+    /**
+     * ChildListener 集合
+     *
+     * key1:节点路径
+     * key2:ChildListener 对象
+     * value :监听器具体对象。不同 Zookeeper 客户端,实现会不同。
+     */
     private final ConcurrentMap<String, ConcurrentMap<ChildListener, TargetChildListener>> childListeners = new ConcurrentHashMap<String, ConcurrentMap<ChildListener, TargetChildListener>>();
-
+    /**
+     * 是否关闭
+     */
     private volatile boolean closed = false;
 
     public AbstractZookeeperClient(URL url) {
         this.url = url;
     }
 
+    @Override
     public URL getUrl() {
         return url;
     }
 
+    @Override
     public void create(String path, boolean ephemeral) {
+        // 循环创建父路径
         int i = path.lastIndexOf('/');
         if (i > 0) {
             String parentPath = path.substring(0, i);
@@ -57,17 +78,21 @@ public void create(String path, boolean ephemeral) {
                 create(parentPath, false);
             }
         }
+        // 创建临时节点
         if (ephemeral) {
             createEphemeral(path);
+        // 创建持久节点
         } else {
             createPersistent(path);
         }
     }
 
+    @Override
     public void addStateListener(StateListener listener) {
         stateListeners.add(listener);
     }
 
+    @Override
     public void removeStateListener(StateListener listener) {
         stateListeners.remove(listener);
     }
@@ -76,36 +101,49 @@ public void removeStateListener(StateListener listener) {
         return stateListeners;
     }
 
+    @Override
     public List<String> addChildListener(String path, final ChildListener listener) {
+        // 获得路径下的监听器数组
         ConcurrentMap<ChildListener, TargetChildListener> listeners = childListeners.get(path);
         if (listeners == null) {
             childListeners.putIfAbsent(path, new ConcurrentHashMap<ChildListener, TargetChildListener>());
             listeners = childListeners.get(path);
         }
+        // 获得是否已经有该监听器
         TargetChildListener targetListener = listeners.get(listener);
+        // 监听器不存在,进行创建
         if (targetListener == null) {
             listeners.putIfAbsent(listener, createTargetChildListener(path, listener));
             targetListener = listeners.get(listener);
         }
+        // 向 Zookeeper ,真正发起订阅
         return addTargetChildListener(path, targetListener);
     }
 
+    @Override
     public void removeChildListener(String path, ChildListener listener) {
         ConcurrentMap<ChildListener, TargetChildListener> listeners = childListeners.get(path);
         if (listeners != null) {
             TargetChildListener targetListener = listeners.remove(listener);
             if (targetListener != null) {
+                // 向 Zookeeper ,真正发起取消订阅
                 removeTargetChildListener(path, targetListener);
             }
         }
     }
 
+    /**
+     * StateListener 数组,回调
+     *
+     * @param state 状态
+     */
     protected void stateChanged(int state) {
         for (StateListener sessionListener : getSessionListeners()) {
             sessionListener.stateChanged(state);
         }
     }
 
+    @Override
     public void close() {
         if (closed) {
             return;
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/zkclient/ZkClientWrapper.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/zkclient/ZkClientWrapper.java
index 3ed350aba0..fd7a87467f 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/zkclient/ZkClientWrapper.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/zkclient/ZkClientWrapper.java
@@ -20,7 +20,6 @@
 import com.alibaba.dubbo.common.logger.Logger;
 import com.alibaba.dubbo.common.logger.LoggerFactory;
 import com.alibaba.dubbo.common.utils.Assert;
-
 import org.I0Itec.zkclient.IZkChildListener;
 import org.I0Itec.zkclient.IZkStateListener;
 import org.I0Itec.zkclient.ZkClient;
@@ -35,14 +34,18 @@
  * Zkclient wrapper class that can monitor the state of the connection automatically after the connection is out of time
  * It is also consistent with the use of curator
  *
+ * 连接超时后,能自动监听连接状态的zkclient包装类
+ * 也为和curator在使用上总体保持一致
+ *
  * @date 2017/10/29
  */
 public class ZkClientWrapper {
-    Logger logger = LoggerFactory.getLogger(ZkClientWrapper.class);
+
+    private Logger logger = LoggerFactory.getLogger(ZkClientWrapper.class);
 
     private long timeout;
     private ZkClient client;
-    private volatile KeeperState state;
+    private volatile KeeperState state; // 多余
     private ListenableFutureTask<ZkClient> listenableFutureTask;
     private volatile boolean started = false;
 
@@ -52,17 +55,21 @@ public ZkClientWrapper(final String serverAddr, long timeout) {
         listenableFutureTask = ListenableFutureTask.create(new Callable<ZkClient>() {
             @Override
             public ZkClient call() throws Exception {
-                return new ZkClient(serverAddr, Integer.MAX_VALUE);
+                return new ZkClient(serverAddr, Integer.MAX_VALUE); // 连接超时设置为无限,在 {@link #start()} 方法中,通过 listenableFutureTask ,实现超时。
             }
         });
     }
 
+    /**
+     * 启动 Zookeeper 客户端
+     */
     public void start() {
         if (!started) {
             Thread connectThread = new Thread(listenableFutureTask);
             connectThread.setName("DubboZkclientConnector");
             connectThread.setDaemon(true);
             connectThread.start();
+            // 连接。若超时,打印错误日志,不会抛出异常。
             try {
                 client = listenableFutureTask.get(timeout, TimeUnit.MILLISECONDS);
             } catch (Throwable t) {
@@ -74,7 +81,13 @@ public void start() {
         }
     }
 
+    /**
+     * 添加状态监听器
+     *
+     * @param listener 监听器
+     */
     public void addListener(final IZkStateListener listener) {
+        // 向 listenableFutureTask 添加监听器。在 listenableFutureTask 执行完成后,在回调方法中,向 client 注册 IZkStateListener 状态监听器。
         listenableFutureTask.addListener(new Runnable() {
             @Override
             public void run() {
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/zkclient/ZkclientZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/zkclient/ZkclientZookeeperClient.java
index a8b4466c1a..18da81f754 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/zkclient/ZkclientZookeeperClient.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/zkclient/ZkclientZookeeperClient.java
@@ -37,7 +37,9 @@
 
     public ZkclientZookeeperClient(URL url) {
         super(url);
+        // 创建 client 对象
         client = new ZkClientWrapper(url.getBackupAddress(), 30000);
+        // 添加连接监听器
         client.addListener(new IZkStateListener() {
             public void handleStateChanged(KeeperState state) throws Exception {
                 ZkclientZookeeperClient.this.state = state;
@@ -52,6 +54,7 @@ public void handleNewSession() throws Exception {
                 stateChanged(StateListener.RECONNECTED);
             }
         });
+        // 启动 client
         client.start();
     }
 
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Exporter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Exporter.java
index ffafddd28f..98985b19bf 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Exporter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Exporter.java
@@ -19,6 +19,8 @@
 /**
  * Exporter. (API/SPI, Prototype, ThreadSafe)
  *
+ * Exporter ,Invoker 暴露服务在 Protocol 上的对象。
+ *
  * @see com.alibaba.dubbo.rpc.Protocol#export(Invoker)
  * @see com.alibaba.dubbo.rpc.ExporterListener
  * @see com.alibaba.dubbo.rpc.protocol.AbstractExporter
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ExporterListener.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ExporterListener.java
index 90f93c1cc9..2701a32cba 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ExporterListener.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ExporterListener.java
@@ -20,6 +20,8 @@
 
 /**
  * ExporterListener. (SPI, Singleton, ThreadSafe)
+ *
+ * Exporter 监听器
  */
 @SPI
 public interface ExporterListener {
@@ -27,8 +29,10 @@
     /**
      * The exporter exported.
      *
-     * @param exporter
-     * @throws RpcException
+     * 当服务暴露完成
+     *
+     * @param exporter Exporter
+     * @throws RpcException RPC 异常
      * @see com.alibaba.dubbo.rpc.Protocol#export(Invoker)
      */
     void exported(Exporter<?> exporter) throws RpcException;
@@ -36,8 +40,10 @@
     /**
      * The exporter unexported.
      *
-     * @param exporter
-     * @throws RpcException
+     * 当服务取消暴露完成
+     *
+     * @param exporter Exporter
+     * @throws RpcException RPC 异常
      * @see com.alibaba.dubbo.rpc.Exporter#unexport()
      */
     void unexported(Exporter<?> exporter);
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Filter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Filter.java
index aed081d35a..f1663148bc 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Filter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Filter.java
@@ -20,6 +20,8 @@
 
 /**
  * Filter. (SPI, Singleton, ThreadSafe)
+ *
+ * 过滤器
  */
 @SPI
 public interface Filter {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Invocation.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Invocation.java
index e5a022074e..7315e1bb11 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Invocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Invocation.java
@@ -21,6 +21,8 @@
 /**
  * Invocation. (API, Prototype, NonThreadSafe)
  *
+ * Invocation 是会话域,它持有调用过程中的变量,比如方法名,参数等。
+ *
  * @serial Don't change the class name and package name.
  * @see com.alibaba.dubbo.rpc.Invoker#invoke(Invocation)
  * @see com.alibaba.dubbo.rpc.RpcInvocation
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Invoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Invoker.java
index b04a56303c..3e77c2517f 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Invoker.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Invoker.java
@@ -21,6 +21,10 @@
 /**
  * Invoker. (API/SPI, Prototype, ThreadSafe)
  *
+ * Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它。
+ * 它代表一个可执行体,可向它发起 invoke 调用。
+ * 它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。
+ *
  * @see com.alibaba.dubbo.rpc.Protocol#refer(Class, com.alibaba.dubbo.common.URL)
  * @see com.alibaba.dubbo.rpc.InvokerListener
  * @see com.alibaba.dubbo.rpc.protocol.AbstractInvoker
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/InvokerListener.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/InvokerListener.java
index 022b51d6d9..efc720d855 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/InvokerListener.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/InvokerListener.java
@@ -21,6 +21,8 @@
 
 /**
  * InvokerListener. (SPI, Singleton, ThreadSafe)
+ *
+ * Invoker 监听器
  */
 @SPI
 public interface InvokerListener {
@@ -28,7 +30,9 @@
     /**
      * The invoker referred
      *
-     * @param invoker
+     * 当服务引用完成
+     *
+     * @param invoker Invoker 对象
      * @throws RpcException
      * @see com.alibaba.dubbo.rpc.Protocol#refer(Class, URL)
      */
@@ -37,7 +41,9 @@
     /**
      * The invoker destroyed.
      *
-     * @param invoker
+     * 当服务销毁引用完成
+     *
+     * @param invoker Invoker 对象
      * @see com.alibaba.dubbo.rpc.Invoker#destroy()
      */
     void destroyed(Invoker<?> invoker);
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Protocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Protocol.java
index b44d49cbb3..c3dcbeaeab 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Protocol.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Protocol.java
@@ -22,6 +22,10 @@
 
 /**
  * Protocol. (API/SPI, Singleton, ThreadSafe)
+ *
+ * 协议接口
+ *
+ * Protocol 是服务域,它是 Invoker 暴露和引用的主功能入口,它负责 Invoker 的生命周期管理。
  */
 @SPI("dubbo")
 public interface Protocol {
@@ -46,6 +50,17 @@
      * @return exporter reference for exported service, useful for unexport the service later
      * @throws RpcException thrown when error occurs during export the service, for example: port is occupied
      */
+    /**
+     * 暴露远程服务:<br>
+     * 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();<br>
+     * 2. export() 必须是幂等的,也就是暴露同一个 URL 的 Invoker 两次,和暴露一次没有区别。<br>
+     * 3. export() 传入的 Invoker 由框架实现并传入,协议不需要关心。<br>
+     *
+     * @param <T>     服务的类型
+     * @param invoker 服务的执行体
+     * @return exporter 暴露服务的引用,用于取消暴露
+     * @throws RpcException 当暴露服务出错时抛出,比如端口已占用
+     */
     @Adaptive
     <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
 
@@ -64,6 +79,18 @@
      * @return invoker service's local proxy
      * @throws RpcException when there's any error while connecting to the service provider
      */
+    /**
+     * 引用远程服务:<br>
+     * 1. 当用户调用 refer() 所返回的 Invoker 对象的 invoke() 方法时,协议需相应执行同 URL 远端 export() 传入的 Invoker 对象的 invoke() 方法。<br>
+     * 2. refer() 返回的 Invoker 由协议实现,协议通常需要在此 Invoker 中发送远程请求。<br>
+     * 3. 当 url 中有设置 check=false 时,连接失败不能抛出异常,并内部自动恢复。<br>
+     *
+     * @param <T>  服务的类型
+     * @param type 服务的类型
+     * @param url  远程服务的URL地址
+     * @return invoker 服务的本地代理
+     * @throws RpcException 当连接服务提供方失败时抛出
+     */
     @Adaptive
     <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
 
@@ -73,6 +100,12 @@
      * 2. Release all occupied resources, for example: connection, port, etc. <br>
      * 3. Protocol can continue to export and refer new service even after it's destroyed.
      */
+    /**
+     * 释放协议:<br>
+     * 1. 取消该协议所有已经暴露和引用的服务。<br>
+     * 2. 释放协议所占用的所有资源,比如连接和端口。<br>
+     * 3. 协议在释放后,依然能暴露和引用新的服务。<br>
+     */
     void destroy();
 
 }
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ProxyFactory.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ProxyFactory.java
index 6ba705717b..5c576b6337 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ProxyFactory.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ProxyFactory.java
@@ -23,6 +23,8 @@
 
 /**
  * ProxyFactory. (API/SPI, Singleton, ThreadSafe)
+ *
+ * 代理工厂接口
  */
 @SPI("javassist")
 public interface ProxyFactory {
@@ -30,7 +32,9 @@
     /**
      * create proxy.
      *
-     * @param invoker
+     * 创建 Proxy ,在引用服务调用。
+     *
+     * @param invoker Invoker 对象
      * @return proxy
      */
     @Adaptive({Constants.PROXY_KEY})
@@ -39,10 +43,12 @@
     /**
      * create invoker.
      *
-     * @param <T>
-     * @param proxy
-     * @param type
-     * @param url
+     * 创建 Invoker ,在暴露服务时调用。
+     *
+     * @param <T> Service 类型
+     * @param proxy Service 对象
+     * @param type Service 类型
+     * @param url 服务的 Dubbo URL
      * @return invoker
      */
     @Adaptive({Constants.PROXY_KEY})
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Result.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Result.java
index 6a74b2b906..d530003b0f 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Result.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/Result.java
@@ -21,6 +21,8 @@
 /**
  * RPC invoke result. (API, Prototype, NonThreadSafe)
  *
+ * Result 是会话域,它持有调用过程中返回值,异常等。
+ *
  * @serial Don't change the class name and package name.
  * @see com.alibaba.dubbo.rpc.Invoker#invoke(Invocation)
  * @see com.alibaba.dubbo.rpc.RpcResult
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
index e7ecebb2e7..78c6afbbd4 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
@@ -43,6 +43,17 @@
  * @export
  * @see com.alibaba.dubbo.rpc.filter.ContextFilter
  */
+/**
+ * Thread local context. (API, ThreadLocal, ThreadSafe)
+ *
+ * 注意:RpcContext是一个临时状态记录器,当接收到RPC请求,或发起RPC请求时,RpcContext的状态都会变化。
+ * 比如:A调B,B再调C,则B机器上,在B调C之前,RpcContext记录的是A调B的信息,在B调C之后,RpcContext记录的是B调C的信息。
+ *
+ * @see com.alibaba.dubbo.rpc.filter.ContextFilter
+ * @author qian.lei
+ * @author william.liangf
+ * @export
+ */
 public class RpcContext {
 
     private static final ThreadLocal<RpcContext> LOCAL = new ThreadLocal<RpcContext>() {
@@ -51,22 +62,38 @@ protected RpcContext initialValue() {
             return new RpcContext();
         }
     };
+
     private final Map<String, String> attachments = new HashMap<String, String>();
     private final Map<String, Object> values = new HashMap<String, Object>();
+    /**
+     * 异步调用 Future
+     */
     private Future<?> future;
 
     private List<URL> urls;
-
+    /**
+     * URL 对象
+     */
     private URL url;
-
+    /**
+     * 方法名
+     */
     private String methodName;
-
+    /**
+     * 参数类型数组
+     */
     private Class<?>[] parameterTypes;
-
+    /**
+     * 参数值数组
+     */
     private Object[] arguments;
-
+    /**
+     * 服务消费者地址
+     */
     private InetSocketAddress localAddress;
-
+    /**
+     * 服务提供者地址
+     */
     private InetSocketAddress remoteAddress;
     @Deprecated
     private List<Invoker<?>> invokers;
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcInvocation.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcInvocation.java
index 245644ed56..0b11323db6 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcInvocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcInvocation.java
@@ -34,15 +34,24 @@
 
     private static final long serialVersionUID = -4355285085441097045L;
 
+    /**
+     * 方法名
+     */
     private String methodName;
-
+    /**
+     * 方法参数类型数组 {@link Method#getParameterTypes()}
+     */
     private Class<?>[] parameterTypes;
-
+    /**
+     * 方法参数数组
+     */
     private Object[] arguments;
-
+    /**
+     * 隐式参数集合
+     */
     private Map<String, String> attachments;
 
-    private transient Invoker<?> invoker;
+    private transient Invoker<?> invoker; // TODO 芋艿,transient
 
     public RpcInvocation() {
     }
@@ -53,22 +62,29 @@ public RpcInvocation(Invocation invocation, Invoker<?> invoker) {
                 invocation.getInvoker());
         if (invoker != null) {
             URL url = invoker.getUrl();
+            // path
             setAttachment(Constants.PATH_KEY, url.getPath());
+            // interface
             if (url.hasParameter(Constants.INTERFACE_KEY)) {
                 setAttachment(Constants.INTERFACE_KEY, url.getParameter(Constants.INTERFACE_KEY));
             }
+            // group
             if (url.hasParameter(Constants.GROUP_KEY)) {
                 setAttachment(Constants.GROUP_KEY, url.getParameter(Constants.GROUP_KEY));
             }
+            // version
             if (url.hasParameter(Constants.VERSION_KEY)) {
                 setAttachment(Constants.VERSION_KEY, url.getParameter(Constants.VERSION_KEY, "0.0.0"));
             }
+            // timeout
             if (url.hasParameter(Constants.TIMEOUT_KEY)) {
                 setAttachment(Constants.TIMEOUT_KEY, url.getParameter(Constants.TIMEOUT_KEY));
             }
+            // token
             if (url.hasParameter(Constants.TOKEN_KEY)) {
                 setAttachment(Constants.TOKEN_KEY, url.getParameter(Constants.TOKEN_KEY));
             }
+            // application
             if (url.hasParameter(Constants.APPLICATION_KEY)) {
                 setAttachment(Constants.APPLICATION_KEY, url.getParameter(Constants.APPLICATION_KEY));
             }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcResult.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcResult.java
index 9a65d7068a..546b7675fb 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcResult.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcResult.java
@@ -47,9 +47,11 @@ public RpcResult(Throwable exception) {
     }
 
     public Object recreate() throws Throwable {
+        // 有异常,抛出异常
         if (exception != null) {
             throw exception;
         }
+        // 无异常,返回结果
         return result;
     }
 
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ServiceClassHolder.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ServiceClassHolder.java
index b480e14be3..02992761a0 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ServiceClassHolder.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ServiceClassHolder.java
@@ -19,11 +19,17 @@
 /**
  * TODO this is just a workaround for rest protocol, and now we just ensure it works in the most common dubbo usages
  *
+ * Service 实现类的 Holder
  */
 public class ServiceClassHolder {
 
+    /**
+     * 单例
+     */
     private static final ServiceClassHolder INSTANCE = new ServiceClassHolder();
-
+    /**
+     * holder
+     */
     private final ThreadLocal<Class> holder  = new ThreadLocal<Class>();
 
     public static ServiceClassHolder getInstance() {
@@ -42,4 +48,5 @@ public Class popServiceClass() {
     public void pushServiceClass(Class clazz) {
         holder.set(clazz);
     }
+
 }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/StaticContext.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/StaticContext.java
index 8db0df644e..bb1adcc822 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/StaticContext.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/StaticContext.java
@@ -27,9 +27,20 @@
  * System context, for internal use only
  */
 public class StaticContext extends ConcurrentHashMap<Object, Object> {
+
     private static final long serialVersionUID = 1L;
+
     private static final String SYSTEMNAME = "system";
+
+    /**
+     * 缓存
+     * key:{@link #name}
+     */
     private static final ConcurrentMap<String, StaticContext> context_map = new ConcurrentHashMap<String, StaticContext>();
+
+    /**
+     * 名字
+     */
     private String name;
 
     private StaticContext(String name) {
@@ -60,10 +71,29 @@ public static String getKey(URL url, String methodName, String suffix) {
         return getKey(url.getServiceKey(), methodName, suffix);
     }
 
+    /**
+     * 获得服务名对应的 {@link #context_map} 键
+     *
+     * @param paras 参数集合
+     * @param methodName 方法名
+     * @param suffix 后缀
+     * @return 键
+     */
     public static String getKey(Map<String, String> paras, String methodName, String suffix) {
         return getKey(StringUtils.getServiceKey(paras), methodName, suffix);
     }
 
+    /**
+     * 获得服务名对应的 {@link #context_map} 键
+     *
+     * 格式,${serviceKey}.${methodName}.${suffix}
+     * 其中,${suffix} 一般是,oninvoke.method、onreturn.method、onthrow.method
+     *
+     * @param servicekey 服务键
+     * @param methodName 方法名
+     * @param suffix 后缀
+     * @return 键
+     */
     private static String getKey(String servicekey, String methodName, String suffix) {
         StringBuffer sb = new StringBuffer().append(servicekey).append(".").append(methodName).append(".").append(suffix);
         return sb.toString();
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ExceptionFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ExceptionFilter.java
index b84fb64648..5830c4dbfd 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ExceptionFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ExceptionFilter.java
@@ -43,6 +43,20 @@
  * <li>Wrap the exception not introduced in API package into RuntimeException. Framework will serialize the outer exception but stringnize its cause in order to avoid of possible serialization problem on client side</li>
  * </ol>
  */
+/**
+ * ExceptionInvokerFilter
+ * <p>
+ * 功能:
+ * <ol>
+ * <li>不期望的异常打ERROR日志(Provider端)<br>
+ * 不期望的日志即是,没有的接口上声明的Unchecked异常。
+ * <li>异常不在API包中,则Wrap一层RuntimeException。<br>
+ * RPC对于第一层异常会直接序列化传输(Cause异常会String化),避免异常在Client出不能反序列化问题。
+ * </ol>
+ *
+ * @author william.liangf
+ * @author ding.lid
+ */
 @Activate(group = Constants.PROVIDER)
 public class ExceptionFilter implements Filter {
 
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/DeprecatedInvokerListener.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/DeprecatedInvokerListener.java
index c5af95de94..73cc11058a 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/DeprecatedInvokerListener.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/DeprecatedInvokerListener.java
@@ -25,6 +25,8 @@
 
 /**
  * DeprecatedProtocolFilter
+ *
+ * 引用废弃的服务时,打印错误日志提醒
  */
 @Activate(Constants.DEPRECATED_KEY)
 public class DeprecatedInvokerListener extends InvokerListenerAdapter {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/ExporterListenerAdapter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/ExporterListenerAdapter.java
index b411a531ae..efcca1344e 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/ExporterListenerAdapter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/ExporterListenerAdapter.java
@@ -22,13 +22,13 @@
 
 /**
  * ExporterListenerAdapter
+ *
+ * ExporterListener 适配器抽象类
  */
 public abstract class ExporterListenerAdapter implements ExporterListener {
 
-    public void exported(Exporter<?> exporter) throws RpcException {
-    }
+    public void exported(Exporter<?> exporter) throws RpcException { }
 
-    public void unexported(Exporter<?> exporter) throws RpcException {
-    }
+    public void unexported(Exporter<?> exporter) throws RpcException { }
 
 }
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/InvokerListenerAdapter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/InvokerListenerAdapter.java
index 64c42565e0..fe416e4d27 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/InvokerListenerAdapter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/listener/InvokerListenerAdapter.java
@@ -22,13 +22,13 @@
 
 /**
  * InvokerListenerAdapter
+ *
+ * InvokerListener 适配器抽象类

  (This diff was longer than 20,000 lines, and has been truncated...)


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

Mime
View raw message