欢迎访问我的个人博客休息的风
学习dubbo,我认为可以从最基本的ExtensionLoader和URL这两个类入手。
据官方介绍,dubbo框架的基本设计原则为:
java spi的具体约定为:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader。
就是通过ServiceLoader加载位于META-INF/services/配置文件,找到具体的实现类名,并装载实例化。而dubbo的ExtensionLoader会加载META-INF/services/、META-INF/dubbo/、META-INF/dubbo/internal/这三个路径配置的类。
具体看下ExtensionLoader的实现,首先ExtensionLoader位于dubbo-common工程的extension包中。
ExtensionLoader的基本方法getExtensionLoader实现为:
@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!"); } //一个type类型对应一个ExtensionLoader实例,并缓存 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; }在new ExtensionLoader时,如果type是ExtensionFactory,会通过getAdaptiveExtension方法,设置适配扩展工厂类;
private ExtensionLoader(Class type) { this.type = type; objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); }getAdaptiveExtension这个方法中,通过createAdaptiveExtension()创建实例并缓存在cachedAdaptiveInstance中。
@SuppressWarnings("unchecked") public T getAdaptiveExtension() {//以DCL方式获取实例,并缓存到cacheAdaptiveInstance中 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); } } } } else { throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); } } return (T) instance; }
@SuppressWarnings("unchecked") private T createAdaptiveExtension() { try { return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e); } }
private Class getAdaptiveExtensionClass() { getExtensionClasses(); if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } return cachedAdaptiveClass = createAdaptiveExtensionClass(); }getAdaptiveExtensionClass这个方法比较复杂,会先调用getExtensionClasses去加载之前说的META-INF/services/、META-INF/dubbo/、META-INF/dubbo/internal/三个目录下,去找以此传入的type类型对应的配置文件,这个配置文件里面的类如果有@Adaptive注解,则加载并直接赋值给cacheAdaptiveClass静态变量;如果配置文件下的类都没有@Adaptive注解,则调用createAdatpiveExtensionClass去生成适配扩展工厂类的代码,并编译加载到内存。
ExtensionLoader 生成的自适应扩展点类如下:(Protocol, ProxyFactory等都是用以下方式生成代码)
package <扩展点接口所在包>;
public class <扩展点接口名>$Adpative implements <扩展点接口> {
public <有@Adaptive注解的接口方法>(<方法参数>) {
if(是否有URL类型方法参数?) 使用该URL参数
else if(是否有方法类型上有URL属性) 使用该URL属性
#
if(获取的URL == null) {
throw new IllegalArgumentException("url == null");
}
根据@Adaptive注解上声明的Key的顺序,从URL获致Value,作为实际扩展点名。
如URL没有Value,则使用缺省扩展点实现。如没有扩展点, throw new IllegalStateException("Fail to get extension");
在扩展点实现调用该方法,并返回结果。
}
public <有@Adaptive注解的接口方法>(<方法参数>) {
throw new UnsupportedOperationException("is not adaptive method!");
}
}
private T injectExtension(T instance) { try { if (objectFactory != null) { for (Method method : instance.getClass().getMethods()) { //以set开头的方法,利用该方法对实例属性进行赋值 if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())) { Class pt = method.getParameterTypes()[0]; try { String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : ""; //objectFactory主要有两个SpiExtensionFactory和SpringExtensionFactory, //获取方法参数需要的类型的实例,调用set方法进行赋值 //SpiExtensionFactory识别pt,也就是类型 //SpringExtensionFactory识别property,也就是名称 Object object = objectFactory.getExtension(pt, property); if (object != null) { method.invoke(instance, object); } } catch (Exception e) { logger.error("fail to inject via method " + method.getName() + " of interface " + type.getName() + ": " + e.getMessage(), e); } } } } } catch (Exception e) { logger.error(e.getMessage(), e); } return instance; }跟spring容器依赖注入相似,采用类的set方法进行属性赋值。至此,一个new ExtensionLoader才算实现完成。
// 此方法已经getExtensionClasses方法同步过。 private Map这三个文件具体的解析加载过程在loadFile中。, Class> loadExtensionClasses() { //type是否有SPI注解 final SPI defaultAnnotation = type.getAnnotation(SPI.class); if (defaultAnnotation != null) { //SPI注解value值为默认的extension,并且只能有一个 String value = defaultAnnotation.value(); if (value != null && (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() + ": " + Arrays.toString(names)); } if (names.length == 1) cachedDefaultName = names[0]; } } Map , Class> extensionClasses = new HashMap , Class>(); //分别加载META-INF/services/、META-INF/dubbo/、META-INF/dubbo/internal/三个目录下的spi loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY); loadFile(extensionClasses, DUBBO_DIRECTORY); loadFile(extensionClasses, SERVICES_DIRECTORY); return extensionClasses; }
private void loadFile(Map有了对loadExtensionClass的分析,createExtension就比较清楚了, Class> extensionClasses, String dir) { //获取文件名 String fileName = dir + type.getName(); try { //获取文件路径 Enumeration 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; while ((line = reader.readLine()) != null) { //忽略配置文件里的#号 final int ci = line.indexOf('#'); if (ci >= 0) line = line.substring(0, ci); line = line.trim(); if (line.length() > 0) { try { 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); //是否和type是同一个接口或是同一个类的子类 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."); } //类有Adaptive注解,就是在getAdaptiveExtensionClass方法要返回的类 if (clazz.isAnnotationPresent(Adaptive.class)) { if (cachedAdaptiveClass == null) { cachedAdaptiveClass = clazz; } else if (!cachedAdaptiveClass.equals(clazz)) { throw new IllegalStateException("More than 1 adaptive class found: " + cachedAdaptiveClass.getClass().getName() + ", " + clazz.getClass().getName()); } } else { try { //类是否为包装类,也就是有以type为参数的构造函数 clazz.getConstructor(type); Set > wrappers = cachedWrapperClasses; if (wrappers == null) { cachedWrapperClasses = new ConcurrentHashSet >(); wrappers = cachedWrapperClasses; } wrappers.add(clazz); } catch (NoSuchMethodException e) { //没有以type为参数的构造函数 clazz.getConstructor(); if (name == null || name.length() == 0) { //兼容旧版本的Extension注解 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(); } else { throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url); } } } String[] names = NAME_SEPARATOR.split(name); if (names != null && names.length > 0) { //类是否有Activate注解,用在getActiveExtension中 Activate activate = clazz.getAnnotation(Activate.class); if (activate != null) { cachedActivates.put(names[0], activate); } for (String n : names) { if (!cachedNames.containsKey(clazz)) { cachedNames.put(clazz, n); } Class c = extensionClasses.get(n); if (c == null) { extensionClasses.put(n, clazz); } else if (c != clazz) { throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName()); }
private T createExtension(String name) { Class clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { //加入实例缓存中 T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } //对实例进行属性依赖注入 injectExtension(instance); //cachedWrapperClasses在loadFile中会赋值 Set> wrapperClasses = cachedWrapperClasses; //构建包装类,并依赖注入,包装类A,B,B包装type值对应的类,A包装B if (wrapperClasses != null && wrapperClasses.size() > 0) { for (Class wrapperClass : wrapperClasses) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } return instance;
public final class URL implements Serializable { private static final long serialVersionUID = -1985165475234910535L; private final String protocol; private final String username; private final String password; private final String host; private final int port; private final String path; private final Map这里举个例子说时url代表的含义:, String> parameters; //这些属性是volatile,说明在多线程下, // 每个属性的值对各个工作内存都是可见的,也就是最新的 // 也是transient,说明url对象作序列化时,这些属性不会参与进序列化 // ==== cache ==== private volatile transient Map , Number> numbers; private volatile transient Map , URL> urls; private volatile transient String ip; private volatile transient String full; private volatile transient String identity; private volatile transient String parameter; private volatile transient String string;