dubbo源码分析 1 -- ExtensionLoader.getExtensionLoader

在dubbo源码中,经常会用到ExtensionLoader, 里面用到java的SPI机制。

ProxyFactory proxyFactory = ExtensionLoader.
getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();

Protocol protocol = ExtensionLoader.
getExtensionLoader(Protocol.class).getAdaptiveExtension();

总结
1. 先判断类是否有@SPI注解
2. 根据指定的目录+类扫描文件里的内容,处理@Advice的类
3. 如果没有则生成XX@Advice的代码,并编译.

类的定义

  • 类上标记@SPI(“xxx”)
  • 方法上标记@Adaptive({Constants.PROXY_KEY})
@SPI("javassist")
public interface ProxyFactory {
    @Adaptive({Constants.PROXY_KEY})
    <T> T getProxy(Invoker<T> invoker) throws RpcException;

    @Adaptive({Constants.PROXY_KEY})
    <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
}


@SPI("dubbo")
public interface Protocol {
    /**
     * 获取缺省端口,当用户没有配置端口时使用。
     * 
     * @return 缺省端口
     */
    int getDefaultPort();

    /**
     * 暴露远程服务:<br>
     * 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext()
     * .setRemoteAddress();
     * 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。
     * 3. export()传入的Invoker由框架实现并传入,协议不需要关心。
     * 
     * @param <T> 服务的类型
     * @param invoker 服务的执行体
     * @return exporter 暴露服务的引用,用于取消暴露
     * @throws RpcException 当暴露服务出错时抛出,比如端口已占用
     */
    @Adaptive
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;

    /**
     * 引用远程服务:<br>
     * 1. 当用户调用refer()所返回的Invoker对象的invoke()方法时,
     * 协议需相应执行同URL远端export()传入的Invoker对象的invoke()方法。
     * 2. refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求。
     * 3. 当url中有设置check=false时,连接失败不能抛出异常,并内部自动恢复。
     * 
     * @param <T> 服务的类型
     * @param type 服务的类型
     * @param url 远程服务的URL地址
     * @return invoker 服务的本地代理
     * @throws RpcException 当连接服务提供方失败时抛出
     */
    @Adaptive
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;

    /**
     * 释放协议:<br>
     * 1. 取消该协议所有已经暴露和引用的服务。
     * 2. 释放协议所占用的所有资源,比如连接和端口。
     * 3. 协议在释放后,依然能暴露和引用新的服务。
     */
    void destroy();
}

获取ExtensionLoader对象

//存在ConcurrentHashMap中
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = 
new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();


public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
     //不是接口,直接报错
     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));
         loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
     }
     return loader;
 }
 //查看类是不是有SPI注解
private static <T> boolean withExtensionAnnotation(Class<T> type) {
    return type.isAnnotationPresent(SPI.class);
}

获取具体的对象

cachedAdaptiveClass : 获取到@Adaptive的类
cachedWrapperClasses : 获取到文件中所有的类

  • 获取对象,没有则创建对象
  public T getAdaptiveExtension() {
        Object instance = cachedAdaptiveInstance.get();
        if (instance == null) {
         //......
            instance = createAdaptiveExtension();
            cachedAdaptiveInstance.set(instance);
         //......
        }

        return (T) instance;
    }
  • 创建对象(获取到类再实例化)
private T createAdaptiveExtension() {
  return injectExtension(   (T) getAdaptiveExtensionClass().newInstance()   );

}
  • 获取到类
private Class<?> getAdaptiveExtensionClass() {
     getExtensionClasses();
     if (cachedAdaptiveClass != null) {
         return cachedAdaptiveClass;
     }
     return cachedAdaptiveClass = createAdaptiveExtensionClass();
 }

1. 根据type扫描指定包下的type文件

扫描指定路径下的所有type文件的内容。
根据文件里的类名去加载类
有@Adaptive的类放入到cachedAdaptiveClass
否则组装到cachedWrapperClasses (key:类,value:是别称)

cachedClasses:将所有的key和class封装起来

  • 加载类
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);
            }
        }
    }
    return classes;
}
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) {
            String[] names = NAME_SEPARATOR.split(value);
            if(names.length == 1) cachedDefaultName = names[0];
        }
    }

    Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
    //通过dir + type.getName()去加载
    //文件META-INF/services/com.alibaba.dubbo.xx.XX
    loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);//META-INF/dubbo/internal/
    loadFile(extensionClasses, DUBBO_DIRECTORY);//META-INF/dubbo/
    loadFile(extensionClasses, SERVICES_DIRECTORY);//META-INF/services/

    return extensionClasses;
 }
  • 加载文件(目录+文件名去加载文件)
private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
   //目录+文件名  META-INF/services/com.alibaba.dubbo.xx.XX
  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()) {
        //省略读取文件...

        //格式如下:
        //spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
          String name = null;
           int i = line.indexOf('=');
           if (i > 0) {
               name = line.substring(0, i).trim();
               line = line.substring(i + 1).trim();
           }
           if (line.length() > 0) {
               Class<?> clazz = Class.forName(line, true, classLoader);
               //如果这个类有Adaptive注解
               if (clazz.isAnnotationPresent(Adaptive.class)) {
                   //记下来
                   if(cachedAdaptiveClass == null) {
                       cachedAdaptiveClass = clazz;
                   }
               } else {
                   try {
                   //cachedWrapperClasses添加类 
                   /**获取它的含有type的构造器
                   SpringExtensionFactory里必须有
                   SpringExtensionFactory(ExtensionFactory factory)构造器**/
                       clazz.getConstructor(type);
                       Set<Class<?>> wrappers = cachedWrapperClasses;
                       if (wrappers == null) {
                           cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
                           wrappers = cachedWrapperClasses;
                       }
                       wrappers.add(clazz);
                   } catch (NoSuchMethodException e) {
                       //获取默认构造器
                       clazz.getConstructor();
                       if (name == null || name.length() == 0) {
                           /**
                           1. 类有注解Extension,获取注解中的值
                           2. 类的名称clazz.getSimpleName()
                            **/
                           name = findAnnotationName(clazz);
                           if (name == null || name.length() == 0) {
                               if (clazz.getSimpleName().length() > type.
                               getSimpleName().length() && clazz.getSimpleName()
                               .endsWith(type.getSimpleName())) {
                                   name = clazz.getSimpleName().substring(0, clazz.
                                   getSimpleName().length() - type.getSimpleName().
                                   length()).toLowerCase();
                               } 
                           }
                       }

                       String[] names = NAME_SEPARATOR.split(name);
                       if (names != null && names.length > 0) {
                           Activate activate = clazz.getAnnotation(Activate.class);
                           if (activate != null) {
                               cachedActivates.put(names[0], activate);
                           }
                           for (String n : names) {
                               //往cachedNames放入类和key(spring)
                               if (! cachedNames.containsKey(clazz)) {
                                   cachedNames.put(clazz, n);
                               }
                               Class<?> c = extensionClasses.get(n);
                               if (c == null) {
                                   extensionClasses.put(n, clazz);
                               } 
                   }
               }
   }
}

@Advice 的类

  • AdaptiveExtensionFactory
public class AdaptiveExtensionFactory implements ExtensionFactory {

private final List<ExtensionFactory> factories;

public AdaptiveExtensionFactory() {
   ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.
    getExtensionLoader(ExtensionFactory.class);
   List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
   for (String name : loader.getSupportedExtensions()) {
       list.add(loader.getExtension(name));
   }
   factories = Collections.unmodifiableList(list);
}

public <T> T getExtension(Class<T> type, String name) {
   for (ExtensionFactory factory : factories) {
       T extension = factory.getExtension(type, name);
       if (extension != null) {
           return extension;
       }
   }
   return null;
}

}
  • SpiExtensionFactory
public class SpiExtensionFactory implements ExtensionFactory {

    public <T> T getExtension(Class<T> type, String name) {
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
            if (loader.getSupportedExtensions().size() > 0) {
                return loader.getAdaptiveExtension();
            }
        }
        return null;
    }

}
  • SpringExtensionFactory
public class SpringExtensionFactory implements ExtensionFactory {

    private static final Set<ApplicationContext> contexts = new 
       ConcurrentHashSet<ApplicationContext>();

    public static void addApplicationContext(ApplicationContext context) {
        contexts.add(context);
    }

    public static void removeApplicationContext(ApplicationContext context) {
        contexts.remove(context);
    }

    @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;
                }
            }
        }
        return null;
    }

}

2. 如果上述没有@Advice的类,那么就自己生成 ExtensionFactory 代码

  1. 创建code代码
  2. 编译
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);
}
  • 创建AdaptiveExtension的代码
private String createAdaptiveExtensionClassCode() {
  StringBuilder codeBuidler = new StringBuilder();
  //遍历类的方法上是否有@Adaptive
  Method[] methods = type.getMethods();
  boolean hasAdaptiveAnnotation = false;
  for(Method m : methods) {
      if(m.isAnnotationPresent(Adaptive.class)) {
          hasAdaptiveAnnotation = true;
          break;
      }
  }

  // 完全没有Adaptive方法,则不需要生成Adaptive类
  if(! hasAdaptiveAnnotation)
      throw new IllegalStateException("");

   //...省略
  return codeBuidler.toString();
}

生成的代码eg:
比如type是Protocol

package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
    public void destroy() {
        throw new UnsupportedOperationException("..");
    }
    public int getDefaultPort() {
        throw new UnsupportedOperationException("..");
    }
    public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) 
      throws com.alibaba.dubbo.rpc.Invoker {
        if (arg0 == null) 
            throw new IllegalArgumentException("..");
        if (arg0.getUrl() == null) 
            throw new IllegalArgumentException("..");
            com.alibaba.dubbo.common.URL url = arg0.getUrl();
            String extName = ( url.getProtocol() == null ?
             "dubbo" : url.getProtocol() );
        if(extName == null) 
            throw new IllegalStateException("..");
        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)
            ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
            .getExtension(extName);
        return extension.export(arg0);
    }

    public com.alibaba.dubbo.rpc.Invoker refer(
        java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) 
        throws java.lang.Class {
        if (arg1 == null) 
            throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg1;
        String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
        if(extName == null) 
            throw new IllegalStateException("..");
        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)
        ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
        .getExtension(extName);
        return extension.refer(arg0, arg1);
    }
}

可以参考https://blog.csdn.net/quhongwei_zhanqiu/article/details/41577235

猜你喜欢

转载自blog.csdn.net/liyue1090041509/article/details/79972508
今日推荐