一文入门dubbo源码

一. 整体设计

1. 简介

dubbo官网的架构设计提供了一张整体的框架图,10个层级看起来挺吓人的。但是其核心总结起来就是:Microkernel + Plugin(微内核+插件)。

2. 设计思想

  1. 采用 URL 作为配置信息的统一格式,所有扩展点都通过传递 URL 携带配置信息
  2. 采用 Microkernel + Plugin 模式,Microkernel 只负责组装 Plugin,Dubbo 自身的功能也是通过扩展点实现的,也就是 Dubbo 的所有功能点都可被用户自定义扩展所替换

3. URL

  1. 属性:
    1. String protocol :一般是 dubbo 中的各种协议 如:dubbo thrift http zk
    2. String host :主机
    3. int port :端口
    4. String path :接口名称
    5. Map<String, String> parameters :参数键值对
    6. String username/password :用户名/密码
  2. 示例:
    1. 服务暴露:registry://registry-host/org.apache.dubbo.registry.RegistryService?export=URL.encode("dubbo://service-host/com.foo.FooService?version=1.0.0")
    2. 服务引用:registry://registry-host/org.apache.dubbo.registry.RegistryService?refer=URL.encode("consumer://consumer-host/com.foo.FooService?version=1.0.0")

4. 图示

在这里插入图片描述

二. Dubbo SPI 理解

注意:上面图中的五个功能块,核心都是围绕着 ExtensionLoader 来进行设计的 ,而 ExtensionLoader 是为了 dubbo SPI 服务,所以这里先对dubbo SPI 做一个简单的理解

1. 简介

SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。

2. 理解

  1. 举例:比如你有个接口,该接口有3个实现类,那么在系统运行时,这个接口到底选择哪个实现类呢?这就需要SPI了,需要根据指定的配置或者是默认的配置,找到对应的实现类加载进来,然后使用该实现类的实例。大白话就是我引用的是接口,想要调用的是接口的impl

接口A => 实现A1,实现A2,实现A3
配置一下,接口A = 实现A2
在系统实际运行的时候,会加载你的配置,用实现A2实例化一个对象来提供服务

3. 基本术语

  1. 扩展点(Extension Point):是一个Java的接口。
  2. 扩展(Extension):扩展点的实现类。
  3. 扩展实例(Extension Instance):扩展点实现类的实例。
  4. 扩展自适应实例(Extension Adaptive Instance):可以理解为扩展代理类,可能更好理解些。扩展的自适应实例其实就是一个Extension的代理,它实现了扩展点接口。在调用扩展点的接口方法时,会根据实际的参数来决定要使用哪个扩展。比如一个IRepository的扩展点,有一个save方法。有两个实现MysqlRepository和MongoRepository。IRepository的自适应实例在调用接口方法的时候,会根据save方法中的参数,来决定要调用哪个IRepository的实现。如果方法参数中有repository=mysql,那么就调用MysqlRepository的save方法。如果repository=mongo,就调用MongoRepository的save方法。和面向对象的延迟绑定很类似。

三. 服务发布与引用详解

整体流程图
在这里插入图片描述

1. 服务发布

时序图

在这里插入图片描述

这里解释一下上面时序图中为什么ServiceBean会直接调用 afterPropertiesSet 方法
在这里插入图片描述

简化流程图

在这里插入图片描述

详细流程图

在这里插入图片描述

2. 服务引用

时序图

在这里插入图片描述

简化流程

在这里插入图片描述

详细流程

在这里插入图片描述

四. Dubbo SPI 源码分析

介绍 Dubbo SPI 之前先来了解一下jdk自带的 Java SPI

1. Java SPI

使用步骤
  1. 首先定义一个接口和两个实现类
//接口
public interface Robot { void sayHello(); }

//两个实现类
public class OptimusPrime implements Robot {
    @Override
    public void sayHello() {
        System.out.println("Hello, I am Optimus Prime.");
    }
}

public class Bumblebee implements Robot {
    @Override
    public void sayHello() {
        System.out.println("Hello, I am Bumblebee.");
    }
}
  1. 然后在 META-INF/services文件夹下创建配置文件,文件名称为这个类的全限定名 org.apache.spi.Robot (没有后缀名,就叫这个)
    1. 作用:当使用这个接口的时候,可以把指定的实现类加载进来,创建的是实现类的实例
org.apache.spi.OptimusPrime
org.apache.spi.Bumblebee
  1. 运行并查看
public class JavaSPITest {
    @Test
    public void sayHello() throws Exception {
        ServiceLoader<Robot> serviceLoader = ServiceLoader.load(Robot.class);
        System.out.println("Java SPI");
        serviceLoader.forEach(Robot::sayHello);
    }
}

在这里插入图片描述

源码分析

首先,ServiceLoader实现了Iterable接口,所以它有迭代器的属性,这里主要都是实现了迭代器的hasNext和next方法。这里主要都是调用的lookupIterator的相应hasNext和next方法,lookupIterator是懒加载迭代器。
其次,LazyIterator中的hasNext方法,静态变量PREFIX就是”META-INF/services/”目录,这也就是为什么需要在classpath下的META-INF/services/目录里创建一个以服务接口命名的文件。
最后,通过反射方法Class.forName()加载类对象,并用newInstance方法将类实例化,并把实例化后的类缓存到providers对象中,(LinkedHashMap<String,S>类型) 然后返回实例对象。

// ServiceLoader实现了Iterable接口,可以遍历所有的服务实现者
public final class ServiceLoader<S> implements Iterable<S>
{
    // 查找配置文件的目录
    private static final String PREFIX = "META-INF/services/";
    // 表示要被加载的服务的类或接口
    private final Class<S> service;
    // 这个ClassLoader用来定位,加载,实例化服务提供者
    private final ClassLoader loader;
    // 访问控制上下文
    private final AccessControlContext acc;
    // 缓存已经被实例化的服务提供者,按照实例化的顺序存储
    private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
    // 迭代器
    private LazyIterator lookupIterator; 
}
// 服务提供者查找的迭代器
public Iterator<S> iterator() {
    return new Iterator<S>() {
        Iterator<Map.Entry<String,S>> knownProviders
            = providers.entrySet().iterator();
        // hasNext方法
        public boolean hasNext() {
            if (knownProviders.hasNext())
                return true;
            return lookupIterator.hasNext();
        }
        // next方法
        public S next() {
            if (knownProviders.hasNext())
                return knownProviders.next().getValue();
            return lookupIterator.next();
        }
    };
}
// 服务提供者查找的迭代器
private class LazyIterator implements Iterator<S> {
    // 服务提供者接口
    Class<S> service;
    // 类加载器
    ClassLoader loader;
    // 保存实现类的url
    Enumeration<URL> configs = null;
    // 保存实现类的全名
    Iterator<String> pending = null;
    // 迭代器中下一个实现类的全名
    String nextName = null;
 
    public boolean hasNext() {
        if (nextName != null) {
            return true;
        }
        if (configs == null) {
            try {
                String fullName = PREFIX + service.getName();
                if (loader == null)
                    configs = ClassLoader.getSystemResources(fullName);
                else
                    configs = loader.getResources(fullName);
            } catch (IOException x) {
                fail(service, "Error locating configuration files", x);
            }
        }
        while ((pending == null) || !pending.hasNext()) {
            if (!configs.hasMoreElements()) {
                return false;
            }
            pending = parse(service, configs.nextElement());
        }
        nextName = pending.next();
        return true;
    }
 
    public S next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        String cn = nextName;
        nextName = null;
        Class<?> c = null;
        try {
            c = Class.forName(cn, false, loader);
        } catch (ClassNotFoundException x) {
            fail(service,"Provider " + cn + " not found");
        }
        if (!service.isAssignableFrom(c)) {
            fail(service, "Provider " + cn  + " not a subtype");
        }
        try {
            S p = service.cast(c.newInstance());
            providers.put(cn, p);
            return p;
        } catch (Throwable x) {
            fail(service, "Provider " + cn + " could not be instantiated: " + x, x);
        }
        throw new Error();          // This cannot happen
    }
}
不足
  1. 不能按需加载:需要遍历所有的实现,并实例化,然后在循环中才能找到我们需要的实现。如果不想用某些实现类,或者某些类实例化很耗时,它也被载入并实例化了,这就造成了浪费。
  2. 获取某个实现类的方式不够灵活:只能通过 Iterator 形式获取,不能根据某个参数来获取对应的实现类。
  3. 线程不安全:多个并发多线程使用 ServiceLoader 类的实例是不安全的。

2. Dubbo SPI

使用步骤
  1. 首先定义一个接口和两个实现类
//接口(Dubbo SPI的接口上要注明 @SPI 注解)
@SPI 
public interface Robot { void sayHello(); }

//两个实现类
public class OptimusPrime implements Robot {
    @Override
    public void sayHello() {
        System.out.println("Hello, I am Optimus Prime.");
    }
}

public class Bumblebee implements Robot {
    @Override
    public void sayHello() {
        System.out.println("Hello, I am Bumblebee.");
    }
}
  1. 然后再META-INF/dubbo文件夹下创建配置文件,文件名称为这个类的全限定名 org.apache.spi.Robot (没有后缀名,就叫这个)
    1. 作用:当使用这个接口的时候,可以把指定的实现类加载进来,创建的是实现类的实例
    2. 与 Java SPI 区别:Dubbo配置是通过键值对的方式(可以按需加载
optimusPrime =org.apache.spi.OptimusPrime
bumblebee =org.apache.spi.Bumblebee
  1. 运行并查看
public class DubboSPITest {
   @Test
   public void sayHello() throws Exception {
       ExtensionLoader<Robot> extensionLoader = 
           ExtensionLoader.getExtensionLoader(Robot.class);
       Robot optimusPrime = extensionLoader.getExtension("optimusPrime");
       optimusPrime.sayHello();
       Robot bumblebee = extensionLoader.getExtension("bumblebee");
       bumblebee.sayHello();
   }
}

在这里插入图片描述

这里只讲解最简单的使用步骤
其中定义的接口中的 @SPI注解 是可以附默认值(配置文件的key)的用来指定创建哪个实现(那么getExtension中就可以填接口的class)
然后定义的接口中的方法上 可以添加@Adaptive 注解 ,也是用来指定创建哪个实现
优先级:@Adaptive标注的类 > URL参数 > @SPI注解中的值
更详细的解释:Dubbo SPI 之 Adaptive 详解

源码分析

基本术语

  1. 扩展点(Extension Point):是一个Java的接口。
  2. 扩展(Extension):扩展点的实现类。
  3. 扩展实例(Extension Instance):扩展点实现类的实例。
  4. 扩展自适应实例(Extension Adaptive Instance):可以理解为扩展代理类,可能更好理解些。扩展的自适应实例其实就是一个Extension的代理,它实现了扩展点接口。在调用扩展点的接口方法时,会根据实际的参数来决定要使用哪个扩展。比如一个IRepository的扩展点,有一个save方法。有两个实现MysqlRepository和MongoRepository。IRepository的自适应实例在调用接口方法的时候,会根据save方法中的参数,来决定要调用哪个IRepository的实现。如果方法参数中有repository=mysql,那么就调用MysqlRepository的save方法。如果repository=mongo,就调用MongoRepository的save方法。和面向对象的延迟绑定很类似。为什么Dubbo会引入扩展自适应实例的概念呢?
代码流程总结
# 获取ExtensionLoader实例
getExtensionLoader()-->
                # ExtensionLoader构造方法
                ExtensionLoader()-->
# 获取一个扩展的自适应实现类 (ps:最后返回的自适应实现类是一个类名为Protocol$Adaptive的类)
getAdaptiveExtension()-->
                # 创建自适应扩展
                createAdaptiveExtension()-->
                                # 获取自适应扩展类
                                getAdaptiveExtensionClass()-->
                                                # 加载扩展类的实现
                                                getExtensionClasses()-->
                                                                # 加载扩展类的实现
                                                                loadExtensionClasses()-->
                                                                                # 加载所有配置文件
                                                                                loadFile()-->
                                                # 通过文件io动态的创建自适应扩展类
                                                createAdaptiveExtensionClass()-->
                                                                # 编译类并返回
                                                                compile()-->
                                                                                # 有name:获取指定名字的扩展( dubbo spi 比 java spi 的优势)
                                                                                loader.getExtension()-->
                                                                                                # 创建扩展实例
                                                                                                createExtension()-->
                                                                                # 无name:获取指定名字的扩展
                                                                                loader.getDefaultExtension()-->
                                                                                                # 加载扩展类的所有实现
                                                                                                loadExtensionClasses()-->
                                                                                                # 获取指定名字的扩展
                                                                                                loader.getExtension()-->
                                                                                # 调用具体的实现类来进行编译然后返回
                                                                                compiler.compile()-->

# 扩展点注入( IOC )
injectExtension()  
拆分理解
  1. setter & Wrapper

    1. setter :扩展点实现类的成员如果为其它扩展点类型,ExtensionLoader 在会自动注入依赖的扩展点。ExtensionLoader 通过扫描扩展点实现类的所有set方法来判定其成员。
      1. 代码位置:injectExtension – 注入扩展点的时候
    2. wrapper :如果扩展点实现类有 拷贝构造函数(一个类的构造函数中入参也是其类的一个对象,对这个对象的属性拷贝后创建新的对象),则认为是包装类。包装类持有实际的扩展点实现类,通过包装类可以把所有扩展点的公共逻辑移到包装类,类似AOP。
      1. 代码位置:createExtension – 实例化扩展点的时候
  2. Adaptive & Activate

    1. Adaptive :扩展点自适应,直到扩展点方法执行时才决定调用哪一个扩展点实现。扩展点的调用会有URL 作为参数,通过@Adaptive 注解可以提取约定 key 来决定调用哪个实现的方法。
      1. 代码位置:loadFile – 判断如果实现类是@Adaptive类型的,会赋值给cachedAdaptiveClass,这个用来存放被@Adaptive注解的实现类
    2. Activate :扩展点自动激活,指定 URL 中激活扩展点的 key,未指定 key 时表示无条件激活
      1. 代码位置:loadFile – 判断如果实现类是@Adaptive类型的,第一个名字作为键,放进cachedActivates这个map中缓存
示例
// 先获取ExtensionLoader实例,然后加载自适应的Protocol扩展点
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
配置文件示例
registry=com.alibaba.dubbo.registry.integration.RegistryProtocol
filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
mock=com.alibaba.dubbo.rpc.support.MockProtocol
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
injvm=com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol
memcached=memcom.alibaba.dubbo.rpc.protocol.memcached.MemcachedProtocol
redis=com.alibaba.dubbo.rpc.protocol.redis.RedisProtocol
rmi=com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol
thrift=com.alibaba.dubbo.rpc.protocol.thrift.ThriftProtocol
com.alibaba.dubbo.rpc.protocol.webservice.WebServiceProtocol
源码分析
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
    //扩展点类型不能为空
    if (type == null)
        throw new IllegalArgumentException();
    //扩展点类型只能是接口类型的
    if(!type.isInterface()) {
        throw new IllegalArgumentException();
    }
    //没有添加@SPI注解,只有注解了@SPI的才会解析
    if(!withExtensionAnnotation(type)) {
        throw new IllegalArgumentException();
    }
    //先从缓存中获取指定类型的ExtensionLoader
    //EXTENSION_LOADERS是一个ConcurrentHashMap,缓存了所有已经加载的ExtensionLoader的实例
    //比如这里加载Protocol.class,就以Protocol.class作为key,以新创建的ExtensionLoader作为value
    //每一个要加载的扩展点只会对应一个ExtensionLoader实例,也就是只会存在一个Protocol.class在缓存中
    ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
    //缓存中不存在
    if (loader == null) {
        //创建一个新的ExtensionLoader实例,放到缓存中去
        //对于每一个扩展,dubbo中只有一个对应的ExtensionLoader实例
        EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
        loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
    }
    return loader;
}


private ExtensionLoader(Class<?> type) {
    //接口类型
    this.type = type;
    //对于扩展类型是ExtensionFactory的,设置为null
    //getAdaptiveExtension方法获取一个运行时自适应的扩展类型
    //每个Extension只能有一个@Adaptive类型的实现,如果么有,dubbo会自动生成一个类
    //objectFactory是一个ExtensionFactory类型的属性,主要用于加载需要注入的类型的实现
    //objectFactory主要用在注入那一步,详细说明见注入时候的说明
    //这里记住非ExtensionFactory类型的返回的都是一个AdaptiveExtensionFactory
    objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}


//用来获取一个扩展的自适应实现类,最后返回的自适应实现类是一个类名为Protocol$Adaptive的类,并且这个类实现了Protocol接口:
public T getAdaptiveExtension() {
    //先从实例缓存中查找实例对象
    //private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
    //在当前的ExtensionLoader中保存着一个Holder实例,用来缓存自适应实现类的实例
    Object instance = cachedAdaptiveInstance.get();
    if (instance == null) {//缓存中不存在
        if(createAdaptiveInstanceError == null) {
            synchronized (cachedAdaptiveInstance) {
                //获取锁之后再检查一次缓存中是不是已经存在
                instance = cachedAdaptiveInstance.get();
                if (instance == null) {
                    try {
                        //缓存中没有,就创建新的AdaptiveExtension实例
                        instance = createAdaptiveExtension();
                        //新实例加入缓存
                        cachedAdaptiveInstance.set(instance);
                    } catch (Throwable t) {createAdaptiveInstanceError = t; }
                }
            }
        }
    }

    return (T) instance;
}

//创建自适应扩展
private T createAdaptiveExtension() {
    try {
        //先通过getAdaptiveExtensionClass获取AdaptiveExtensionClass
        //然后获取其实例
        //最后进行注入处理
        return injectExtension((T) getAdaptiveExtensionClass().newInstance());
    } catch (Exception e) {}
}


//获取自适应扩展类
private Class<?> getAdaptiveExtensionClass() {
    //加载当前Extension的所有实现(这里举例是Protocol,只会加载Protocol的所有实现类),如果有@Adaptive类型的实现类,会赋值给cachedAdaptiveClass
    //目前只有AdaptiveExtensionFactory和AdaptiveCompiler两个实现类是被注解了@Adaptive
    //除了ExtensionFactory和Compiler类型的扩展之外,其他类型的扩展都是下面动态创建的的实现
    getExtensionClasses();
    //加载完所有的实现之后,发现有cachedAdaptiveClass不为空
    //也就是说当前获取的自适应实现类是AdaptiveExtensionFactory或者是AdaptiveCompiler,就直接返回,这两个类是特殊用处的,不用代码生成,而是现成的代码
    if (cachedAdaptiveClass != null) {
        return cachedAdaptiveClass;
    }
    //没有找到Adaptive类型的实现,动态创建一个
    //比如Protocol的实现类,没有任何一个实现是用@Adaptive来注解的,只有Protocol接口的方法是有注解的
    //这时候就需要来动态的生成了,也就是生成Protocol$Adaptive
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
}

//加载扩展类实现
private Map<String, Class<?>> getExtensionClasses() {
    //从缓存中获取,cachedClasses也是一个Holder,Holder这里持有的是一个Map,key是扩展点实现名,value是扩展点实现类
    //这里会存放当前扩展点类型的所有的扩展点的实现类
    //这里以Protocol为例,就是会存放Protocol的所有实现类
    //比如key为dubbo,value为com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
    //cachedClasses扩展点实现名称对应的实现类
    Map<String, Class<?>> classes = cachedClasses.get();
    //如果为null,说明没有被加载过,就会进行加载,而且加载就只会进行这一次
    if (classes == null) {
        synchronized (cachedClasses) {
            classes = cachedClasses.get();
            if (classes == null) {
                //如果没有加载过Extension的实现,进行扫描加载,完成后缓存起来
                //每个扩展点,其实现的加载只会这执行一次
                classes = loadExtensionClasses();
                cachedClasses.set(classes);
            }
        }
    }
    return classes;
}


//加载扩展点的实现类
private Map<String, Class<?>> loadExtensionClasses() {
    final SPI defaultAnnotation = type.getAnnotation(SPI.class);
    if(defaultAnnotation != null) {
        //当前Extension的默认实现名字
        //比如说Protocol接口,注解是@SPI("dubbo")
        //这里dubbo就是默认的值
        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();
            }
            //默认的名字保存起来
            if(names.length == 1) cachedDefaultName = names[0];
        }
    }

    //下面就开始从配置文件中加载扩展实现类
    Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
    //从META-INF/dubbo/internal目录下加载
    loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
    //从META-INF/dubbo/目录下加载
    loadFile(extensionClasses, DUBBO_DIRECTORY);
    //从META-INF/services/下加载
    loadFile(extensionClasses, SERVICES_DIRECTORY);
    return extensionClasses;
}


private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
    //配置文件的名称
    //这里type是扩展类,比如com.alibaba.dubbo.rpc.Protocol类
    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;
                        //每次处理一行
                        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是Protocol接口
                                        //clazz就是Protocol的各个实现类
                                        if (! type.isAssignableFrom(clazz)) {
                                            throw new IllegalStateException();
                                        }
                                        //如果实现类是@Adaptive类型的,会赋值给cachedAdaptiveClass,这个用来存放被@Adaptive注解的实现类
                                        if (clazz.isAnnotationPresent(Adaptive.class)) {
                                            if(cachedAdaptiveClass == null) {
                                                cachedAdaptiveClass = clazz;
                                            } else if (! cachedAdaptiveClass.equals(clazz)) {
                                                throw new IllegalStateException();
                                            }
                                        } else {//不是@Adaptice类型的类,就是没有注解@Adaptive的实现类
                                            try {//判断是否是wrapper类型
                                                //如果得到的实现类的构造方法中的参数是扩展点类型的,就是一个Wrapper类
                                                //比如ProtocolFilterWrapper,实现了Protocol类,
                                                //而它的构造方法是这样public ProtocolFilterWrapper(Protocol protocol)
                                                //就说明这个类是一个包装类
                                                clazz.getConstructor(type);
                                                //cachedWrapperClasses用来存放当前扩展点实现类中的包装类
                                                Set<Class<?>> wrappers = cachedWrapperClasses;
                                                if (wrappers == null) {
                                                    cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
                                                    wrappers = cachedWrapperClasses;
                                                }
                                                wrappers.add(clazz);
                                            } catch (NoSuchMethodException e) {
                                            //没有上面提到的构造器,则说明不是wrapper类型
                                                //获取无参构造
                                                clazz.getConstructor();
                                                //没有名字,就是配置文件中没有xxx=xxxx.com.xxx这种
                                                if (name == null || name.length() == 0) {
                                                    //去找@Extension注解中配置的值
                                                    name = findAnnotationName(clazz);
                                                    //如果还没找到名字,从类名中获取
                                                    if (name == null || name.length() == 0) {
                                                        //比如clazz是DubboProtocol,type是Protocol
                                                        //这里得到的name就是dubbo
                                                        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("");
                                                        }
                                                    }
                                                }
                                                //有可能配置了多个名字
                                                String[] names = NAME_SEPARATOR.split(name);
                                                if (names != null && names.length > 0) {
                                                    //是否是Active类型的类
                                                    Activate activate = clazz.getAnnotation(Activate.class);
                                                    if (activate != null) {
                                                        //第一个名字作为键,放进cachedActivates这个map中缓存
                                                        cachedActivates.put(names[0], activate);
                                                    }
                                                    for (String n : names) {
                                                        if (! cachedNames.containsKey(clazz)) {
                                                            //放入Extension实现类与名称映射的缓存中去,每个class只对应第一个名称有效
                                                            cachedNames.put(clazz, n);
                                                        }
                                                        Class<?> c = extensionClasses.get(n);
                                                        if (c == null) {
                                                            //放入到extensionClasses缓存中去,多个name可能对应一份extensionClasses
                                                            extensionClasses.put(n, clazz);
                                                        } else if (c != clazz) {
                                                            throw new IllegalStateException();
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                } catch (Throwable t) { }
                            }
                        } // end of while read lines
                    } finally {
                        reader.close();
                    }
                } catch (Throwable t) { }
            } // end of while urls
        }
    } catch (Throwable t) { }
}


//创建自适应扩展类的代码
private Class<?> createAdaptiveExtensionClass() {
    //组装自适应扩展点类的代码
    String code = createAdaptiveExtensionClassCode();
    //获取到应用的类加载器
    ClassLoader classLoader = findClassLoader();
    //获取编译器
    //dubbo默认使用javassist
    //这里还是使用扩展点机制来找具体的Compiler的实现
    //现在就知道cachedAdaptiveClass是啥意思了,如果没有AdaptiveExtensionFactory和AdaptiveCompiler这两个类,这里又要去走加载流程然后来生成扩展点类的代码,不就死循环了么。
    //这里解析Compiler的实现类的时候,会在getAdaptiveExtensionClass中直接返回
    //可以查看下AdaptiveCompiler这个类,如果我们没有指定,默认使用javassist
    //这里Compiler是JavassistCompiler实例
    com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
    //将代码转换成Class
    return compiler.compile(code, classLoader);
}



private String createAdaptiveExtensionClassCode() {
    ....
    for (Method method : methods) {
        Class<?> rt = method.getReturnType();
        Class<?>[] pts = method.getParameterTypes();
        Class<?>[] ets = method.getExceptionTypes();

        Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
        StringBuilder code = new StringBuilder(512);
        //对应的自适应注解的方法此处会重点逻辑  
        if (adaptiveAnnotation == null) {
            code.append("throw new UnsupportedOperationException(\"method ")
                    .append(method.toString()).append(" of interface ")
                    .append(type.getName()).append(" is not adaptive method!\");");
        } else {
            ....
        }
    }
    codeBuidler.append("\n}");
    if (logger.isDebugEnabled()) {
        logger.debug(codeBuidler.toString());
    }
    return codeBuidler.toString();
}

public Class<?> compile(String code, ClassLoader classLoader) {
    Compiler compiler;
    //得到一个ExtensionLoader
    ExtensionLoader<Compiler> loader = ExtensionLoader.getExtensionLoader(Compiler.class);
    //默认的Compiler名字
    String name = DEFAULT_COMPILER; // copy reference
    //有指定了Compiler名字,就使用指定的名字来找到Compiler实现类
    if (name != null && name.length() > 0) {
        compiler = loader.getExtension(name);
    } else {//没有指定Compiler名字,就查找默认的Compiler的实现类
        compiler = loader.getDefaultExtension();
    }
    //调用具体的实现类来进行编译
    return compiler.compile(code, classLoader);
}


//获取指定名字的扩展

public T getExtension(String name) {
    if (name == null || name.length() == 0)
        throw new IllegalArgumentException("Extension name == null");
    //如果name指定为true,则获取默认实现
    if ("true".equals(name)) {
        //默认实现查找在下面解析
        return getDefaultExtension();
    }
    //先从缓存获取Holder,cachedInstance是一个ConcurrentHashMap,键是扩展的name,值是一个持有name对应的实现类实例的Holder。
    Holder<Object> holder = cachedInstances.get(name);
    //如果当前name对应的Holder不存在,就创建一个,添加进map中
    if (holder == null) {
        cachedInstances.putIfAbsent(name, new Holder<Object>());
        holder = cachedInstances.get(name);
    }
    //从Holder中获取保存的实例
    Object instance = holder.get();
    //不存在,就需要根据这个name找到实现类,实例化一个
    if (instance == null) {
        synchronized (holder) {
            instance = holder.get();
            if (instance == null) {
                //缓存不存在,创建实例
                instance = createExtension(name);
                //加入缓存
                holder.set(instance);
            }
        }
    }
    //存在,就直接返回
    return (T) instance;
}

//创建扩展实例
private T createExtension(String name) {
    //getExtensionClasses加载当前Extension的所有实现
    //上面已经解析过,返回的是一个Map,键是name,值是name对应的Class
    //根据name查找对应的Class
    Class<?> clazz = getExtensionClasses().get(name);
    //如果这时候class还不存在,说明在所有的配置文件中都没找到定义,抛异常
    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);
        //Wrapper的包装
        Set<Class<?>> wrapperClasses = cachedWrapperClasses;
        if (wrapperClasses != null && wrapperClasses.size() > 0) {
            for (Class<?> wrapperClass : wrapperClasses) {
                instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
            }
        }
        return instance;
    } catch (Throwable t) { }
}


//获取默认扩展实现
public T getDefaultExtension() {
    //首先还是先去加载所有的扩展实现
    //加载的时候会设置默认的名字cachedDefaultName,这个名字是在@SPI中指定的,比如Compiler就指定了@SPI("javassist"),所以这里是javassist
    getExtensionClasses();
    if(null == cachedDefaultName || cachedDefaultName.length() == 0
            || "true".equals(cachedDefaultName)) {
        return null;
    }
    //根据javassist这个名字去查找扩展实现
    //具体的过程上面已经解析过了
    return getExtension(cachedDefaultName);
}


 private T createAdaptiveExtension() {
    try {
        //先通过getAdaptiveExtensionClass获取AdaptiveExtensionClass(在上面这一步已经解析了,获得到了一个自适应实现类的Class)
        //然后获取其实例,newInstance进行实例
        //最后进行注入处理injectExtension
        return injectExtension((T) getAdaptiveExtensionClass().newInstance());
    } catch (Exception e) { }
}



//这里的实例是Xxxx$Adaptive
private T injectExtension(T instance) {
    try {
        //关于objectFactory的来路,先看下面的解析
        //这里的objectFactory是AdaptiveExtensionFactory
        if (objectFactory != null) {
            //遍历扩展实现类实例的方法
            for (Method method : instance.getClass().getMethods()) {
                //只处理set方法
                //set开头,只有一个参数,public
                if (method.getName().startsWith("set")
                        && method.getParameterTypes().length == 1
                        && Modifier.isPublic(method.getModifiers())) {
                    //set方法参数类型
                    Class<?> pt = method.getParameterTypes()[0];
                    try {
                        //setter方法对应的属性名
                        String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                        //根据类型和名称信息从ExtensionFactory中获取
                        //比如在某个扩展实现类中会有setProtocol(Protocol protocol)这样的set方法
                        //这里pt就是Protocol,property就是protocol
                        //AdaptiveExtensionFactory就会根据这两个参数去查找对应的扩展实现类
                        //这里就会返回Protocol$Adaptive
                        Object object = objectFactory.getExtension(pt, property);
                        if (object != null) {//说明set方法的参数是扩展点类型,进行注入
                            //为set方法注入一个自适应的实现类
                            method.invoke(instance, object);
                        }
                    } catch (Exception e) { }
                }
            }
        }
    } catch (Exception e) {}
    return instance;
}

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值