第一章 dubbo源码解析目录

重要的网址:

第一个dubbo项目

首先从https://github.com/alibaba/dubbo下载dubbo源码到本地,我们的第一个dubbo项目就是dubbo源码中的dubbo-demo子模块。

代码结构如下:

其中:

  • dubbo-demo-api是提供服务接口的模块
    • 在生产中,该模块会单独打成jar包,分别被provider和consumer依赖,provider实现该接口,consumer通过该接口引用provider实现的服务
  • dubbo-demo-provider是服务提供者
  • dubbo-demo-consumer是服务消费者

 

一 dubbo-demo-api

1 package com.alibaba.dubbo.demo;
2 
3 public interface DemoService {
4     String sayHello(String name);
5 }

只提供了一个接口。

 

二 dubbo-demo-provider

1 配置文件

src/main/resources/META-INF/spring/dubbo-demo-provider.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
 4        xmlns="http://www.springframework.org/schema/beans"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 6        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 7 
 8     <!-- 提供方应用信息,用于计算依赖关系 -->
 9     <dubbo:application name="demo-provider"/>
10 
11     <!-- 使用zookeeper注册中心,并使用curator客户端 -->
12     <dubbo:registry protocol="zookeeper" address="10.211.55.5:2181" client="curator"/>
13 
14     <!-- 使用dubbo协议在20880端口暴露服务 -->
15     <dubbo:protocol name="dubbo" port="20880"/>
16 
17     <!-- 和本地bean一样实现服务 -->
18     <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
19 
20     <!-- 声明需要暴露的服务接口 -->
21     <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
22 </beans>

配置项:

  • dubbo:application:指定应用名字,在生产中通常与artifactId相同
  • dubbo:registry:指定注册中心
    • protocol:使用的注册协议
    • address:注册中心地址
    • client:默认情况下,操作zookeeper的java客户端使用的是zkClient,这里使用curator
  • dubbo:protocol:指定服务暴露的协议和端口
  • dubbo:service:生命暴露的服务接口及其实现类

2 provider提供服务接口实现

 1 package com.alibaba.dubbo.demo.provider;
 2 
 3 import com.alibaba.dubbo.demo.DemoService;
 4 import com.alibaba.dubbo.rpc.RpcContext;
 5 
 6 import java.text.SimpleDateFormat;
 7 import java.util.Date;
 8 
 9 public class DemoServiceImpl implements DemoService {
10     public String sayHello(String name) {
11         System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
12         return "Hello " + name + ", response form provider: " + RpcContext.getContext().getLocalAddress();
13     }
14 }

3 provider启动类

 1 package com.alibaba.dubbo.demo.provider;
 2 
 3 import org.springframework.context.support.ClassPathXmlApplicationContext;
 4 
 5 public class Provider {
 6     public static void main(String[] args) throws Exception {
 7         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
 8         context.start();
 9 
10         System.in.read(); // 按任意键退出
11     }
12 }

 

三 dubbo-demo-consumer

1 配置文件

src/main/resources/META-INF/spring/dubbo-demo-consumer.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
 4        xmlns="http://www.springframework.org/schema/beans"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 6        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 7 
 8     <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
 9     <dubbo:application name="demo-consumer"/>
10 
11     <!-- 使用zookeeper注册中心,并使用curator客户端 -->
12     <dubbo:registry protocol="zookeeper" address="10.211.55.5:2181" client="curator"/>
13 
14     <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
15     <dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService"/>
16 </beans>

配置项:

  • dubbo:reference:指定引用的服务
    • check:检查注册中心是否有可用的 provider

2 consumer启动类

 1 package com.alibaba.dubbo.demo.consumer;
 2 
 3 import com.alibaba.dubbo.demo.DemoService;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class Consumer {
 7     public static void main(String[] args) {
 8         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
 9         context.start();
10 
11         DemoService demoService = (DemoService) context.getBean("demoService"); // 获取远程服务代理
12         String hello = demoService.sayHello("world"); // 执行远程方法
13 
14         System.out.println(hello); // 显示调用结果
15     }
16 }

 启动服务并且调用远程服务。

 

四 启动服务

1 启动provider

启动成功后,会发现在zookeeper上创建了节点:

/dubbo

--/com.alibaba.dubbo.demo.DemoService

----/providers

------/dubbo://10.10.10.10:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=1393&side=provider&timestamp=1506831679007

注意:

  • 所有dubbo相关的都会注册在“/dubbo”根节点下
  • 与当前暴露的接口服务相关的,都注册在“/dubbo/接口”下

2 启动consumer

启动成功后,会发现在zookeeper上创建了节点:

/dubbo

--/com.alibaba.dubbo.demo.DemoService

----/consumers

------/consumer://10.10.10.10/com.alibaba.dubbo.demo.DemoService?application=demo-consumer&category=consumers&check=false&dubbo=2.0.0&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&pid=1434&side=consumer&timestamp=1506832498078

 

之后,看到provider和consumer双方的互动输出,则表示rpc成功!

第一个dubbo项目就结束了,dubbo-demo项目也可以查看http://dubbo.io/的例子。

2.1 jdk-spi的实现原理

dubbo-spi是在jdk-spi的基础上进行重写优化,下面看一下jdk-spi。

一、作用

  • 为接口自动寻找实现类。

二、实现方式

  • 标准制定者制定接口
  • 不同厂商编写针对于该接口的实现类,并在jar的“classpath:META-INF/services/全接口名称”文件中指定相应的实现类全类名
  • 开发者直接引入相应的jar,就可以实现为接口自动寻找实现类的功能

三、使用方法

注意:示例以Log体系为例,但是实际中的Log体系并不是这样来实现的。

1、pom.xml

1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5     <modelVersion>4.0.0</modelVersion>
6     <groupId>com.hulk</groupId>
7     <artifactId>java-spi</artifactId>
8     <version>1.0-SNAPSHOT</version>
9 </project>

2、标准接口:com.hulk.javaspi.Log

1 package com.hulk.javaspi;
2 
3 public interface Log {
4     void execute();
5 }

3、具体实现1:com.hulk.javaspi.Log4j

1 package com.hulk.javaspi;
2 
3 public class Log4j implements Log {
4     @Override
5     public void execute() {
6         System.out.println("log4j ...");
7     }
8 }

4、具体实现2:com.hulk.javaspi.Logback

1 package com.hulk.javaspi;
2 
3 public class Logback implements Log {
4     @Override
5     public void execute() {
6         System.out.println("logback ...");
7     }
8 }

5、指定使用的实现文件:META-INF/services/com.hulk.javaspi.Log

1 com.hulk.javaspi.Logback

注意

  • 这里指定了实现类Logback,那么加载的时候就会自动为Log接口指定实现类为Logback。
  • 这里也可以指定两个实现类,那么在实际中使用哪一个实现类,就需要使用额外的手段来控制。
    1 com.hulk.javaspi.Logback
    2 com.hulk.javaspi.Log4j

6、加载实现主类:com.hulk.javaspi.Main

 1 package com.hulk.javaspi;
 2 
 3 import java.util.Iterator;
 4 import java.util.ServiceLoader;
 5 
 6 public class Main {
 7     public static void main(String[] args) {
 8         ServiceLoader<Log> serviceLoader = ServiceLoader.load(Log.class);
 9         Iterator<Log> iterator = serviceLoader.iterator();
10         while (iterator.hasNext()) {
11             Log log = iterator.next();
12             log.execute();
13         }
14     }
15 }

注意:

  • ServiceLoader不是实例化以后,就去读取配置文件中的具体实现,并进行实例化。而是等到使用迭代器去遍历的时候,才会加载对应的配置文件去解析,调用hasNext方法的时候会去加载配置文件进行解析,调用next方法的时候进行实例化并缓存 - 具体见“源码分析”

现在来解析Main的源码。

四、源码解析

1、获取ServiceLoader

1 ServiceLoader<Log> serviceLoader = ServiceLoader.load(Log.class);

源码:

首先来看一下ServiceLoader的6个属性

1      private static final String PREFIX = "META-INF/services/";//定义实现类的接口文件所在的目录
2      private final Class<S> service;//接口
3      private final ClassLoader loader;//定位、加载、实例化实现类
4      private final AccessControlContext acc;//权限控制上下文
5      private LinkedHashMap<String,S> providers = new LinkedHashMap<>();//以初始化的顺序缓存<接口全名称, 实现类实例>
6      private LazyIterator lookupIterator;//真正进行迭代的迭代器

其中LazyIterator是ServiceLoader的一个内部类,在迭代部分会说。

 1     public static <S> ServiceLoader<S> load(Class<S> service) {
 2         ClassLoader cl = Thread.currentThread().getContextClassLoader();
 3         return ServiceLoader.load(service, cl);
 4     }
 5 
 6     public static <S> ServiceLoader<S> load(Class<S> service,
 7                                             ClassLoader loader) {
 8         return new ServiceLoader<>(service, loader);
 9     }
10 
11     private ServiceLoader(Class<S> svc, ClassLoader cl) {
12         service = Objects.requireNonNull(svc, "Service interface cannot be null");
13         loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
14         acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
15         reload();
16     }
17 
18     public void reload() {
19         providers.clear();//清空缓存
20         lookupIterator = new LazyIterator(service, loader);
21     }

这样一个ServiceLoader实例就创建成功了。在创建的过程中,我们看到还实例化了一个LazyIterator,该类下边会说。

2、获取迭代器并迭代

1          Iterator<Log> iterator = serviceLoader.iterator();
2          while (iterator.hasNext()) {
3              Log log = iterator.next();
4              log.execute();
5          }

外层迭代器:

 1     public Iterator<S> iterator() {
 2         return new Iterator<S>() {
 3 
 4             Iterator<Map.Entry<String,S>> knownProviders
 5                 = providers.entrySet().iterator();
 6 
 7             public boolean hasNext() {
 8                 if (knownProviders.hasNext())
 9                     return true;
10                 return lookupIterator.hasNext();
11             }
12 
13             public S next() {
14                 if (knownProviders.hasNext())
15                     return knownProviders.next().getValue();
16                 return lookupIterator.next();
17             }
18 
19             public void remove() {
20                 throw new UnsupportedOperationException();
21             }
22 
23         };
24     }

 从查找过程hasNext()和迭代过程next()来看。

  • hasNext():先从provider(缓存)中查找,如果有,直接返回true;如果没有,通过LazyIterator来进行查找。
  • next():先从provider(缓存)中直接获取,如果有,直接返回实现类对象实例;如果没有,通过LazyIterator来进行获取。

下面来看一下,LazyIterator这个类。首先看一下他的属性:

1         Class<S> service;//接口
2         ClassLoader loader;//类加载器
3         Enumeration<URL> configs = null;//存放配置文件
4         Iterator<String> pending = null;//存放配置文件中的内容,并存储为ArrayList,即存储多个实现类名称
5         String nextName = null;//当前处理的实现类名称

其中,service和loader在上述实例化ServiceLoader的时候就已经实例化好了。

下面看一下hasNext():

 1         public boolean hasNext() {
 2             if (acc == null) {
 3                 return hasNextService();
 4             } else {
 5                 PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
 6                     public Boolean run() { return hasNextService(); }
 7                 };
 8                 return AccessController.doPrivileged(action, acc);
 9             }
10         }
11 
12         private boolean hasNextService() {
13             if (nextName != null) {
14                 return true;
15             }
16             if (configs == null) {
17                 try {
18                     String fullName = PREFIX + service.getName();
19                     if (loader == null)
20                         configs = ClassLoader.getSystemResources(fullName);
21                     else
22                         configs = loader.getResources(fullName);
23                 } catch (IOException x) {
24                     fail(service, "Error locating configuration files", x);
25                 }
26             }
27             while ((pending == null) || !pending.hasNext()) {
28                 if (!configs.hasMoreElements()) {
29                     return false;
30                 }
31                 pending = parse(service, configs.nextElement());
32             }
33             nextName = pending.next();
34             return true;
35         }

hasNextService()中,核心实现如下:

  • 首先使用loader加载配置文件,此时找到了META-INF/services/com.hulk.javaspi.Log文件;
  • 然后解析这个配置文件,并将各个实现类名称存储在pending的ArrayList中; -->  此时[ com.hulk.javaspi.Logback ]
  • 最后指定nextName; --> 此时nextName=com.hulk.javaspi.Logback

 下面看一下next():

 1         public S next() {
 2             if (acc == null) {
 3                 return nextService();
 4             } else {
 5                 PrivilegedAction<S> action = new PrivilegedAction<S>() {
 6                     public S run() { return nextService(); }
 7                 };
 8                 return AccessController.doPrivileged(action, acc);
 9             }
10         }
11 
12         private S nextService() {
13             if (!hasNextService())
14                 throw new NoSuchElementException();
15             String cn = nextName;
16             nextName = null;
17             Class<?> c = null;
18             try {
19                 c = Class.forName(cn, false, loader);
20             } catch (ClassNotFoundException x) {
21                 fail(service,
22                      "Provider " + cn + " not found");
23             }
24             if (!service.isAssignableFrom(c)) {
25                 fail(service,
26                      "Provider " + cn  + " not a subtype");
27             }
28             try {
29                 S p = service.cast(c.newInstance());
30                 providers.put(cn, p);
31                 return p;
32             } catch (Throwable x) {
33                 fail(service,
34                      "Provider " + cn + " could not be instantiated",
35                      x);
36             }
37             throw new Error();          // This cannot happen
38         }

nextService()中,核心实现如下:

  • 首先加载nextName代表的类Class,这里为com.hulk.javaspi.Logback;
  • 之后创建该类的实例,并转型为所需的接口类型
  • 最后存储在provider中,供后续查找,最后返回转型后的实现类实例。

再next()之后,拿到实现类实例后,就可以执行其具体的方法了。

五、缺点

  • 查找一个具体的实现需要遍历查找,耗时;-->此时就体现出Collection相较于Map差的地方,map可以直接根据key来获取具体的实现 (dubbo-spi实现了根据key获取具体实现的方式)

2.2 dubbo-spi源码解析

 
 1 package com.alibaba.dubbo.demo.test;
 2 
 3 import com.alibaba.dubbo.common.extension.ExtensionLoader;
 4 import com.alibaba.dubbo.rpc.Protocol;
 5 
 6 public class TestExtension {
 7     public static void main(String[] args) {
 8         ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
 9         final Protocol dubboProtocol = loader.getExtension("dubbo");
10         final Protocol adaptiveExtension = loader.getAdaptiveExtension();
11     }
12 }

讲解这三行代码的源码。

一  Protocol接口的定义

 1 package com.alibaba.dubbo.rpc;
 2 
 3 import com.alibaba.dubbo.common.URL;
 4 import com.alibaba.dubbo.common.extension.Adaptive;
 5 import com.alibaba.dubbo.common.extension.SPI;
 6 
 7 /**
 8  * Protocol. (API/SPI, Singleton, ThreadSafe)
 9  */
10 @SPI("dubbo")
11 public interface Protocol {
12 
13     /**
14      * 获取缺省端口,当用户没有配置端口时使用。
15      *
16      * @return 缺省端口
17      */
18     int getDefaultPort();
19 
20     /**
21      * 暴露远程服务:<br>
22      * 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();<br>
23      * 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。<br>
24      * 3. export()传入的Invoker由框架实现并传入,协议不需要关心。<br>
25      *
26      * @param <T>     服务的类型
27      * @param invoker 服务的执行体
28      * @return exporter 暴露服务的引用,用于取消暴露
29      * @throws RpcException 当暴露服务出错时抛出,比如端口已占用
30      */
31     @Adaptive
32     <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
33 
34     /**
35      * 引用远程服务:<br>
36      * 1. 当用户调用refer()所返回的Invoker对象的invoke()方法时,协议需相应执行同URL远端export()传入的Invoker对象的invoke()方法。<br>
37      * 2. refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求。<br>
38      * 3. 当url中有设置check=false时,连接失败不能抛出异常,并内部自动恢复。<br>
39      *
40      * @param <T>  服务的类型
41      * @param type 服务的类型
42      * @param url  远程服务的URL地址
43      * @return invoker 服务的本地代理
44      * @throws RpcException 当连接服务提供方失败时抛出
45      */
46     @Adaptive
47     <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
48 
49     /**
50      * 释放协议:<br>
51      * 1. 取消该协议所有已经暴露和引用的服务。<br>
52      * 2. 释放协议所占用的所有资源,比如连接和端口。<br>
53      * 3. 协议在释放后,依然能暴露和引用新的服务。<br>
54      */
55     void destroy();
56 }

注意:这里有两个核心注解

  • @SPI:指定一个接口为SPI接口(可扩展接口)
    1 @Documented
    2 @Retention(RetentionPolicy.RUNTIME)
    3 @Target({ElementType.TYPE})
    4 public @interface SPI {
    5     /** 缺省扩展点名 */
    6     String value() default "";
    7 } 
  • @Adaptive该注解可以注解在两个地方:

    • 接口上:例如AdaptiveExtensionFactory(该类不是工厂类,有特殊的逻辑)  AdaptiveCompiler(实际上也是工厂类,但是不能靠动态生成,否则会形成死循环)
    • 接口的方法上:会动态生成相应的动态类(实际上是一个工厂类,工厂设计模式),例如Protocol$Adapter

这个接口极其重要,后续的整个服务暴露和服务调用会用到该接口的两个方法。

 

二 获取ExtensionLoader

1 ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);

ExtensionLoader可以类比为JDK-SPI中的ServiceLoader。

首先来看一下ExtensionLoader的类属性:

 1     /** 存放SPI文件的三个目录,其中META-INF/services/也是jdk的SPI文件的存放目录 */
 2     private static final String SERVICES_DIRECTORY = "META-INF/services/";
 3     private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
 4     private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";//这个是最终jar包中存放spi文件的位置
 5 
 6     private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
 7     /** key: SPI接口Class value: 该接口的ExtensionLoader */
 8     private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
 9     /** key: SPI接口Class value: SPI实现类的对象实例 */
10     private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();

注意:上述的都是类属性,即所有该类的实例都共享。而后边的实例属性就属于每一个类的实例私有。

再来看一下ExtensionLoader的实例属性:

 1     /** SPI接口Class */
 2     private final Class<?> type;
 3     /** SPI实现类对象实例的创建工厂 */
 4     private final ExtensionFactory objectFactory;
 5     /** key: ExtensionClass的Class value: SPI实现类的key */
 6     private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();
 7     /** 存放所有的extensionClass */
 8     private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>();
 9 
10     private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();
11     /** 缓存创建好的extensionClass实例 */
12     private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
13     /** 缓存创建好的适配类实例 */
14     private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
15     /** 存储类上带有@Adaptive注解的Class */
16     private volatile Class<?> cachedAdaptiveClass = null;
17     /** 默认的SPI文件中的key */
18     private String cachedDefaultName;
19     /** 存储在创建适配类实例这个过程中发生的错误 */
20     private volatile Throwable createAdaptiveInstanceError;
21     /** 存放具有一个type入参的构造器的实现类的Class对象 */
22     private Set<Class<?>> cachedWrapperClasses;
23     /** key :实现类的全类名  value: exception, 防止真正的异常被吞掉 */
24     private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();

来看一下getExtensionLoader(Class<T> type)的源码:

 1     /**
 2      * 1 校验入参type:非空 + 接口 + 含有@SPI注解
 3      * 2 根据type接口从全局缓存EXTENSION_LOADERS中获取ExtensionLoader,如果有直接返回;如果没有,则先创建,之后放入缓存,最后返回
 4      */
 5     public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
 6         if (type == null)
 7             throw new IllegalArgumentException("Extension type == null");
 8         if (!type.isInterface()) {
 9             throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
10         }
11         if (!withExtensionAnnotation(type)) {
12             throw new IllegalArgumentException("Extension type(" + type +
13                     ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
14         }
15 
16         ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
17         if (loader == null) {
18             EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
19             loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
20         }
21         return loader;
22     }

创建ExtensionLoader:

1     private ExtensionLoader(Class<?> type) {
2         this.type = type;
3         objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
4     }

当前创建的ExtensionLoader对象(我们取名为ExtensionLoader对象1)的type是com.alibaba.dubbo.rpc.Protocol,所以此时会执行:ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()。

首先是创建ExtensionFactory,通过上边核心类部分ExtensionFactory接口的源码可以看出,此类也是一个SPI接口类,且没有指定默认的实现类的key。

1 ExtensionLoader.getExtensionLoader(ExtensionFactory.class)

下面的代码与上述的过程相似,只是此时创建的另外一个ExtensionLoader对象(我们取名为ExtensionLoader对象2)的type是com.alibaba.dubbo.common.extension.ExtensionFactory,而objectFactory是null。之后,这个ExtensionLoader对象2被放入EXTENSION_LOADERS缓存。这里给出ExtensionFactory的定义,该类也极其重要。//TODO

1 package com.alibaba.dubbo.common.extension;
2 
3 @SPI
4 public interface ExtensionFactory {
5     <T> T getExtension(Class<T> type, String name);
6 }

之后执行ExtensionLoader对象2的getAdaptiveExtension()方法。

 1     /**
 2      * 首先从cachedAdaptiveInstance缓存中获取AdaptiveExtension实例
 3      * 如果不为null, 直接返回;
 4      * 如果为null, 先创建AdaptiveExtension实例, 之后放入cachedAdaptiveInstance缓存中,最后返回
 5      */
 6     public T getAdaptiveExtension() {
 7         Object instance = cachedAdaptiveInstance.get();
 8         if (instance == null) {
 9             if (createAdaptiveInstanceError == null) {
10                 synchronized (cachedAdaptiveInstance) {
11                     instance = cachedAdaptiveInstance.get();
12                     if (instance == null) {
13                         try {
14                             instance = createAdaptiveExtension();
15                             cachedAdaptiveInstance.set(instance);
16                         } catch (Throwable t) {
17                             createAdaptiveInstanceError = t;
18                             throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
19                         }
20                     }
21                 }
22             } else {
23                 throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
24             }
25         }
26 
27         return (T) instance;
28     }

来看createAdaptiveExtension()创建AdaptiveExtension的源码:

 1     /**
 2      * createAdaptiveExtension()
 3      * --getAdaptiveExtensionClass()
 4      *   //从dubbo-spi配置文件中获取AdaptiveExtensionClass
 5      *   --getExtensionClasses()
 6      *     --loadExtensionClasses()
 7      *       --loadFile(Map<String, Class<?>> extensionClasses, String dir)
 8      *   //创建动态代理类
 9      *   --createAdaptiveExtensionClass()
10      *
11      * --injectExtension(T instance)  //dubbo-ioc
12      */
13     private T createAdaptiveExtension() {
14         try {
15             return injectExtension((T) getAdaptiveExtensionClass().newInstance());
16         } catch (Exception e) {
17             throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e);
18         }
19     }

调用层级看注释。injectExtension(T instance)方法只对objectFactory有用,如果objectFactory==null,则直接返回T instance。所以这里返回的是getAdaptiveExtensionClass().newInstance()

来看getAdaptiveExtensionClass()的源码:

 1     /**
 2      * 获取ExtensionClasses和适配类
 3      * 如果实现类上带有@Adaptive注解,直接创建修饰类
 4      * 如果方法上带有@Adaptive注解,动态生成代理类
 5      */
 6     private Class<?> getAdaptiveExtensionClass() {
 7         getExtensionClasses();
 8         if (cachedAdaptiveClass != null) {
 9             return cachedAdaptiveClass;
10         }
11         return cachedAdaptiveClass = createAdaptiveExtensionClass();
12     }

现在来看getExtensionClasses():

 1     /**
 2      * 先从cachedClasses缓存中获取所有的ExtensionClass,如果有,直接返回;
 3      * 如果没有,通过loadExtensionClasses()从SPI文件中去读取,之后写入缓存
 4      */
 5     private Map<String, Class<?>> getExtensionClasses() {
 6         Map<String, Class<?>> classes = cachedClasses.get();
 7         if (classes == null) {
 8             synchronized (cachedClasses) {
 9                 classes = cachedClasses.get();
10                 if (classes == null) {
11                     classes = loadExtensionClasses();
12                     cachedClasses.set(classes);
13                 }
14             }
15         }
16         return classes;
17     }

现在来看loadExtensionClasses()

 1     /**
 2      * 1 从@SPI注解中将默认值解析出来,并缓存到cachedDefaultName中
 3      * 2 从SPI文件中获取extensionClass并存储到extensionClasses中,最后返回extensionClasses
 4      * 注意:此方法已经getExtensionClasses方法同步过。
 5      */
 6     private Map<String, Class<?>> loadExtensionClasses() {
 7         final SPI defaultAnnotation = type.getAnnotation(SPI.class);
 8         if (defaultAnnotation != null) {
 9             String value = defaultAnnotation.value();
10             if (value != null && (value = value.trim()).length() > 0) {
11                 String[] names = NAME_SEPARATOR.split(value);
12                 if (names.length > 1) {
13                     throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
14                             + ": " + Arrays.toString(names));
15                 }
16                 if (names.length == 1) cachedDefaultName = names[0];
17             }
18         }
19 
20         Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
21         loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
22         loadFile(extensionClasses, DUBBO_DIRECTORY);
23         loadFile(extensionClasses, SERVICES_DIRECTORY);
24         return extensionClasses;
25     }

之后来看一下非常重要的一个方法loadFile(Map<String, Class<?>> extensionClasses, String dir)。

  1     /**
  2      * 1 加载dir目录下的指定type名称的文件(例如:dubbo-2.5.5.jar中的/META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory)
  3      * 2 遍历该文件中的每一行
  4      * (1)获取实现类key和value, 例如 name=spi, line=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
  5      * (2)根据line创建Class对象
  6      * (3)将具有@Adaptive注解的实现类的Class对象放在cachedAdaptiveClass缓存中, 注意该缓存只能存放一个具有@Adaptive注解的实现类的Class对象,如果有两个满足条件,则抛异常
  7      * 下面的都是对不含@Adaptive注解的实现类的Class对象:
  8      * (4)查看是否具有含有一个type入参的构造器, 如果有(就是wrapper类), 将当前的Class对象放置到cachedWrapperClasses缓存中
  9      * (5)如果没有含有一个type入参的构造器, 获取无参构造器. 如果Class对象具有@Active注解, 将该对象以<实现类的key, active>存储起来
 10      * (6)最后,将<Class对象, 实现类的key>存入cachedNames缓存,并将这些Class存入extensionClasses中.
 11      * @param extensionClasses
 12      * @param dir
 13      */
 14     private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
 15         String fileName = dir + type.getName();
 16         try {
 17             Enumeration<java.net.URL> urls;
 18             ClassLoader classLoader = findClassLoader();
 19             if (classLoader != null) {
 20                 urls = classLoader.getResources(fileName);
 21             } else {
 22                 urls = ClassLoader.getSystemResources(fileName);
 23             }
 24             if (urls != null) {
 25                 while (urls.hasMoreElements()) {
 26                     java.net.URL url = urls.nextElement();
 27                     try {
 28                         BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
 29                         try {
 30                             String line = null;
 31                             while ((line = reader.readLine()) != null) {
 32                                 final int ci = line.indexOf('#');
 33                                 if (ci >= 0) line = line.substring(0, ci);
 34                                 line = line.trim();
 35                                 if (line.length() > 0) {
 36                                     try {
 37                                         String name = null;
 38                                         int i = line.indexOf('=');
 39                                         if (i > 0) {
 40                                             name = line.substring(0, i).trim();
 41                                             line = line.substring(i + 1).trim();
 42                                         }
 43                                         if (line.length() > 0) {
 44                                             Class<?> clazz = Class.forName(line, true, classLoader);
 45                                             if (!type.isAssignableFrom(clazz)) {
 46                                                 throw new IllegalStateException("Error when load extension class(interface: " +
 47                                                         type + ", class line: " + clazz.getName() + "), class "
 48                                                         + clazz.getName() + "is not subtype of interface.");
 49                                             }
 50                                             if (clazz.isAnnotationPresent(Adaptive.class)) {
 51                                                 if (cachedAdaptiveClass == null) {
 52                                                     cachedAdaptiveClass = clazz;
 53                                                 } else if (!cachedAdaptiveClass.equals(clazz)) {
 54                                                     throw new IllegalStateException("More than 1 adaptive class found: "
 55                                                             + cachedAdaptiveClass.getClass().getName()
 56                                                             + ", " + clazz.getClass().getName());
 57                                                 }
 58                                             } else {
 59                                                 try {
 60                                                     clazz.getConstructor(type);
 61                                                     Set<Class<?>> wrappers = cachedWrapperClasses;
 62                                                     if (wrappers == null) {
 63                                                         cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
 64                                                         wrappers = cachedWrapperClasses;
 65                                                     }
 66                                                     wrappers.add(clazz);
 67                                                 } catch (NoSuchMethodException e) {
 68                                                     clazz.getConstructor();
 69                                                     if (name == null || name.length() == 0) {
 70                                                         name = findAnnotationName(clazz);
 71                                                         if (name == null || name.length() == 0) {
 72                                                             if (clazz.getSimpleName().length() > type.getSimpleName().length()
 73                                                                     && clazz.getSimpleName().endsWith(type.getSimpleName())) {
 74                                                                 name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - type.getSimpleName().length()).toLowerCase();
 75                                                             } else {
 76                                                                 throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url);
 77                                                             }
 78                                                         }
 79                                                     }
 80                                                     String[] names = NAME_SEPARATOR.split(name);
 81                                                     if (names != null && names.length > 0) {
 82                                                         Activate activate = clazz.getAnnotation(Activate.class);
 83                                                         if (activate != null) {
 84                                                             cachedActivates.put(names[0], activate);
 85                                                         }
 86                                                         for (String n : names) {
 87                                                             if (!cachedNames.containsKey(clazz)) {
 88                                                                 cachedNames.put(clazz, n);
 89                                                             }
 90                                                             Class<?> c = extensionClasses.get(n);
 91                                                             if (c == null) {
 92                                                                 extensionClasses.put(n, clazz);
 93                                                             } else if (c != clazz) {
 94                                                                 throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName());
 95                                                             }
 96                                                         }
 97                                                     }
 98                                                 }
 99                                             }
100                                         }
101                                     } catch (Throwable t) {
102                                         IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
103                                         exceptions.put(line, e);
104                                     }
105                                 }
106                             } // end of while read lines
107                         } finally {
108                             reader.close();
109                         }
110                     } catch (Throwable t) {
111                         logger.error("Exception when load extension class(interface: " +
112                                 type + ", class file: " + url + ") in " + url, t);
113                     }
114                 } // end of while urls
115             }
116         } catch (Throwable t) {
117             logger.error("Exception when load extension class(interface: " +
118                     type + ", description file: " + fileName + ").", t);
119         }
120     }

上述的方法分别从三个目录查找SPI文件并进行加载。在这里只有在META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory中有值,内容如下:

1 adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
2 spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
3 spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory

其中AdaptiveExtensionFactory在类上具有@Adaptive注解,这个类会在后续去讲,这里先略过。

执行过后,看一下:

  • cachedAdaptiveClass=class com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
  • extensionClasses=[{"spring","class com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory"}, {"spi", "class com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory"}],后续会这个集合存储在cachedClasses缓存中。

上边一直在讲解getAdaptiveExtensionClass().newInstance()这句代码中的getAdaptiveExtensionClass(),此方法返回一个com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory类,之后来看一下其newInstance()代码,调用这个方法,默认会执行AdaptiveExtensionFactory的无参构造器。这里给出AdaptiveExtensionFactory的完整代码:

 1 package com.alibaba.dubbo.common.extension.factory;
 2 
 3 import com.alibaba.dubbo.common.extension.Adaptive;
 4 import com.alibaba.dubbo.common.extension.ExtensionFactory;
 5 import com.alibaba.dubbo.common.extension.ExtensionLoader;
 6 
 7 import java.util.ArrayList;
 8 import java.util.Collections;
 9 import java.util.List;
10 
11 /**
12  * AdaptiveExtensionFactory
13  */
14 @Adaptive
15 public class AdaptiveExtensionFactory implements ExtensionFactory {
16     private final List<ExtensionFactory> factories;
17 
18     /**
19      * 遍历cachedClasses中缓存的extensionClasses的key,之后根据key来实例化对应的实现类,最后放置到EXTENSION_INSTANCES缓存中
20      */
21     public AdaptiveExtensionFactory() {
22         ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
23         List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
24         for (String name : loader.getSupportedExtensions()) {
25             list.add(loader.getExtension(name));
26         }
27         factories = Collections.unmodifiableList(list);
28     }
29 
30     public <T> T getExtension(Class<T> type, String name) {
31         for (ExtensionFactory factory : factories) {
32             T extension = factory.getExtension(type, name);
33             if (extension != null) {
34                 return extension;
35             }
36         }
37         return null;
38     }
39 }

从上可以看出,这个装饰类只是实例化好了各个ExtensionFactory(这里是SpiExtensionFactory和SpringExtensionFactory),后续通过工厂获取实现类实例都是由具体工厂来完成。

来看一下实例化代码的地方,即loader.getExtension(name):

 1     /**
 2      * 从cachedInstances缓存中获取name对应的实例,如果没有,通过createExtension(name)创建,之后放入缓存
 3      * getExtension(String name)
 4      * --createExtension(String name)
 5      * ----injectExtension(T instance)
 6      */
 7     public T getExtension(String name) {
 8         if (name == null || name.length() == 0)
 9             throw new IllegalArgumentException("Extension name == null");
10         if ("true".equals(name)) {
11             return getDefaultExtension();
12         }
13         Holder<Object> holder = cachedInstances.get(name);
14         if (holder == null) {
15             cachedInstances.putIfAbsent(name, new Holder<Object>());
16             holder = cachedInstances.get(name);
17         }
18         Object instance = holder.get();
19         if (instance == null) {
20             synchronized (holder) {
21                 instance = holder.get();
22                 if (instance == null) {
23                     instance = createExtension(name);
24                     holder.set(instance);
25                 }
26             }
27         }
28         return (T) instance;
29     }

来看一下创建createExtension(name):

 1     private T createExtension(String name) {
 2         /** 从cachedClasses缓存中获取所有的实现类map,之后通过name获取到对应的实现类的Class对象 */
 3         Class<?> clazz = getExtensionClasses().get(name);
 4         if (clazz == null) {
 5             throw findException(name);
 6         }
 7         try {
 8             /** 从EXTENSION_INSTANCES缓存中获取对应的实现类的Class对象,如果没有,直接创建,之后放入缓存 */
 9             T instance = (T) EXTENSION_INSTANCES.get(clazz);
10             if (instance == null) {
11                 EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
12                 instance = (T) EXTENSION_INSTANCES.get(clazz);
13             }
14             injectExtension(instance);//ioc
15             Set<Class<?>> wrapperClasses = cachedWrapperClasses;
16             if (wrapperClasses != null && wrapperClasses.size() > 0) {
17                 for (Class<?> wrapperClass : wrapperClasses) {
18                     instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
19                 }
20             }
21             return instance;
22         } catch (Throwable t) {
23             throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
24                     type + ")  could not be instantiated: " + t.getMessage(), t);
25         }
26     }

这里,就体现出来了dubbo-SPI比JDK-SPI的好处:dubbo-SPI不需要遍历所有的实现类来获取想要的实现类,可以直接通过name来获取。

injectExtension(instance)和wrapper包装功能后续再说。

 

到此为止,ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);这行代码的整个源码就讲述完成了。最后来看一下整个代码的执行结果。

类变量

  • ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS
    • "interface com.alibaba.dubbo.rpc.Protocol" -> "com.alibaba.dubbo.common.extension.ExtensionLoader[com.alibaba.dubbo.rpc.Protocol]"
    • "interface com.alibaba.dubbo.common.extension.ExtensionFactory" -> "com.alibaba.dubbo.common.extension.ExtensionLoader[com.alibaba.dubbo.common.extension.ExtensionFactory]"
  • ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES
    • "class com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory" -> SpringExtensionFactory实例
    • "class com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory" -> SpiExtensionFactory实例

ExtensionLoader<Protocol> loader的实例变量

  • Class<?> type = interface com.alibaba.dubbo.rpc.Protocol
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
    • factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]

总结:

第一点:ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(Class<T> type)最终得到的实例变量是:

  • Class<?> type = interface T
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
    • factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]

第二点:ExtensionLoader<T>.getAdaptiveExtension()的调用层级

1 ExtensionLoader<T>.getAdaptiveExtension()
2 --createAdaptiveExtension()
3 ----injectExtension(getAdaptiveExtensionClass())
4 ------getAdaptiveExtensionClass()
5 --------getExtensionClasses()//从spi文件中查找实现类上具有@Adaptive注解的类
6 ----------loadExtensionClasses()
7 ------------loadFile(Map<String, Class<?>> extensionClasses, String dir)
8 --------createAdaptiveExtensionClass()//如果从spi文件中没有找到实现类上具有@Adaptive注解的类,则动态创建类

最终返回的是创建好的Adaptive类,例如AdaptiveExtensionFactory实例。

第三点:ExtensionLoader<T>.getExtension()的调用层级

1 ExtensionLoader<T>.getExtension()
2 --createExtension(String name)
3 ----getExtensionClasses().get(name)//获取扩展类
4 ----injectExtension(instance);//ioc
5 ----wrapper包装;//aop

最终返回的是创建好的具体实现类,例如SpringExtensionFactory实例。 

第三章 dubbo内核之ioc源码解析

dubbo的IOC具体实现在:T injectExtension(T instance)方法中。该方法只在三个地方被使用:

1 createAdaptiveExtension()
2 --injectExtension((T) getAdaptiveExtensionClass().newInstance()) //为创建好的AdaptiveExtensionClass实例进行属性注入
3 
4 createExtension(String name)
5 --injectExtension(instance) //为创建好的Extension实例进行属性注入
6 --injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)) //为创建好的wrapperClass实例进行属性注入

来看一下源码:

 1     /**
 2      * dubbo-IOC的核心
 3      */
 4     private T injectExtension(T instance) {
 5         try {
 6             if (objectFactory != null) {
 7                 for (Method method : instance.getClass().getMethods()) {
 8                     if (method.getName().startsWith("set") && method.getParameterTypes().length == 1
 9                         && Modifier.isPublic(method.getModifiers())) {//一个参数的public的setXXX(T param)方法.例如,setName(String name)
10                         Class<?> pt = method.getParameterTypes()[0];//参数param的类型T,eg.String
11                         try {
12                             String property = method.getName().length() > 3
13                                 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";//获取属性名XXX, eg.name
14                             Object object = objectFactory.getExtension(pt, property);//实例化参数
15                             if (object != null) {
16                                 //执行instance.method(object)方法,这里就是执行instance的setter方法,进行setter注入
17                                 method.invoke(instance, object);
18                             }
19                         } catch (Exception e) {
20                             logger.error("fail to inject via method " + method.getName() + " of interface "
21                                          + type.getName() + ": " + e.getMessage(),
22                                 e);
23                         }
24                     }
25                 }
26             }
27         } catch (Exception e) {
28             logger.error(e.getMessage(), e);
29         }
30         return instance;
31     }

整个方法的作用就是通过instance对象实例的setter方法为instance的属性赋值,完成setter注入,即IOC的最经典的注入方式。

详细步骤:

  • 获取instance的setter方法,通过setter方法获取属性名称property和属性类型pt(即paramType的简写)
  • 使用objectFactory创建一个property名称(类型为pt)的对象实例
  • 执行instance的setter方法,注入property实例

其中,比较重要的就是:Object object = objectFactory.getExtension(pt, property);这个方法。其中的objectFactory=AdaptiveExtensionFactory实例,其属性factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]。

看一下源码:

 1     private final List<ExtensionFactory> factories;
 2 
 3     public <T> T getExtension(Class<T> type, String name) {
 4         /**
 5          * 先调用SpiExtensionFactory来实例化;
 6          * 如果不行,再使用SpringExtensionFactory来实例化
 7          */
 8         for (ExtensionFactory factory : factories) {
 9             T extension = factory.getExtension(type, name);
10             if (extension != null) {
11                 return extension;
12             }
13         }
14         return null;
15     }

看一下SpiExtensionFactory的源码:

 1 public class SpiExtensionFactory implements ExtensionFactory {
 2     public <T> T getExtension(Class<T> type, String name) {
 3         if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {//type是接口且必须具有@SPI注解
 4             ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
 5             if (loader.getSupportedExtensions().size() > 0) {//获取type的所有ExtensionClasses实现的key
 6                 return loader.getAdaptiveExtension();//获取type的装饰类,如果有@Adaptive注解的类,则返回该类的实例,否则返回一个动态代理类的实例(例如Protocol$Adpative的实例)
 7             }
 8         }
 9         return null;
10     }
11 }

从这里我们可以看出dubbo-SPI的另外一个好处:可以为SPI实现类注入SPI的装饰类或动态代理类。

看一下SpringExtensionFactory的源码:

 1 public class SpringExtensionFactory implements ExtensionFactory {
 2     private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>();
 3     
 4     public static void addApplicationContext(ApplicationContext context) {
 5         contexts.add(context);
 6     }
 7 
 8     public static void removeApplicationContext(ApplicationContext context) {
 9         contexts.remove(context);
10     }
11 
12     @SuppressWarnings("unchecked")
13     public <T> T getExtension(Class<T> type, String name) {
14         for (ApplicationContext context : contexts) {
15             if (context.containsBean(name)) {//该context是否包含name的bean
16                 Object bean = context.getBean(name);//获取name的bean,如果是懒加载或多例的bean,此时会实例化name的bean
17                 if (type.isInstance(bean)) {//如果obj的类型是type或其子类,与instanceof相同
18                     return (T) bean;
19                 }
20             }
21         }
22         return null;
23     }
24 }

至此,IOC就干完了。但是有一个遗留问题,ApplicationContext是什么时候加入到contexts中呢?当讲解ServiceBean的时候来说。

 

第四章 dubbo内核之aop源码解析

1         ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
2         final Protocol dubboProtocol = loader.getExtension("dubbo");
3         final Protocol adaptiveExtension = loader.getAdaptiveExtension();

第一行代码在2.2 dubbo-spi源码解析中讲过,本节来看第二行代码。

 

一、获取一个ExtensionLoader

第一行代码后获得的loader:

  • Class<?> type = interface com.alibaba.dubbo.rpc.Protocol
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
    • factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]

 

二、getExtension("dubbo")

调用层级:

1 ExtensionLoader<T>.getExtension()
2 --createExtension(String name)
3 ----getExtensionClasses().get(name)//获取扩展类
4 ------loadExtensionClasses()
5 --------loadFile(Map<String, Class<?>> extensionClasses, String dir)
6 ----injectExtension(instance);//ioc
7 ----wrapper包装;//aop

createExtension(String name),该方法源码如下:

 1     private T createExtension(String name) {
 2         /** 从cachedClasses缓存中获取所有的实现类map,之后通过name获取到对应的实现类的Class对象 */
 3         Class<?> clazz = getExtensionClasses().get(name);
 4         if (clazz == null) {
 5             throw findException(name);
 6         }
 7         try {
 8             /** 从EXTENSION_INSTANCES缓存中获取对应的实现类的Class对象,如果没有,直接创建,之后放入缓存 */
 9             T instance = (T) EXTENSION_INSTANCES.get(clazz);
10             if (instance == null) {
11                 EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
12                 instance = (T) EXTENSION_INSTANCES.get(clazz);
13             }
14             injectExtension(instance);
15             Set<Class<?>> wrapperClasses = cachedWrapperClasses;
16             if (wrapperClasses != null && wrapperClasses.size() > 0) {
17                 for (Class<?> wrapperClass : wrapperClasses) {
18                     instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
19                 }
20             }
21             return instance;
22         } catch (Throwable t) {
23             throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
24                                             + ")  could not be instantiated: " + t.getMessage(),
25                 t);
26         }
27     }

这里,先给出META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol内容:

 1 registry=com.alibaba.dubbo.registry.integration.RegistryProtocol
 2 dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
 3 filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
 4 listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
 5 mock=com.alibaba.dubbo.rpc.support.MockProtocol
 6 injvm=com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol
 7 rmi=com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol
 8 hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
 9 com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
10 com.alibaba.dubbo.rpc.protocol.webservice.WebServiceProtocol
11 thrift=com.alibaba.dubbo.rpc.protocol.thrift.ThriftProtocol
12 memcached=com.alibaba.dubbo.rpc.protocol.memcached.MemcachedProtocol
13 redis=com.alibaba.dubbo.rpc.protocol.redis.RedisProtocol

com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper和com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper,这两个类不含有@Adaptive注解且具有含有Protocol的单参构造器,符合这样条件的会被列入AOP增强类。放置在loader的私有属性cachedWrapperClasses中。

此时的loader:

  • Class<?> type = interface com.alibaba.dubbo.rpc.Protocol
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
    • factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]
  • cachedWrapperClasses = [class ProtocolListenerWrapper, class ProtocolFilterWrapper]

再来看createExtension(String name)中的红色部分,就是今天的重点AOP。如上所讲,我在cachedWrapperClasses中缓存了两个AOP增强类:class ProtocolListenerWrapper和class ProtocolFilterWrapper。

首先是获取ProtocolListenerWrapper的单参构造器,然后创建ProtocolListenerWrapper实例,最后完成对ProtocolListenerWrapper实例进行属性注入,注意此时的instance=ProtocolListenerWrapper实例,而不再是之前的DubboProtocol实例了。之后使用ProtocolFilterWrapper以同样的方式进行包装,只是此时ProtocolFilterWrapper包装的是ProtocolListenerWrapper实例,也就是类似于这样的关系:

1 instance = ProtocolFilterWrapper实例 {
2       protocol = ProtocolListenerWrapper实例 {
3           protocol = DubboProtocol实例
4       }  
5 }    

来看一下ProtocolListenerWrapper源码:

 1 package com.alibaba.dubbo.rpc.protocol;
 2 
 3 import com.alibaba.dubbo.common.Constants;
 4 import com.alibaba.dubbo.common.URL;
 5 import com.alibaba.dubbo.common.extension.ExtensionLoader;
 6 import com.alibaba.dubbo.rpc.Exporter;
 7 import com.alibaba.dubbo.rpc.ExporterListener;
 8 import com.alibaba.dubbo.rpc.Invoker;
 9 import com.alibaba.dubbo.rpc.InvokerListener;
10 import com.alibaba.dubbo.rpc.Protocol;
11 import com.alibaba.dubbo.rpc.RpcException;
12 import com.alibaba.dubbo.rpc.listener.ListenerExporterWrapper;
13 import com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper;
14 
15 import java.util.Collections;
16 
17 public class ProtocolListenerWrapper implements Protocol {
18     private final Protocol protocol;
19 
20     public ProtocolListenerWrapper(Protocol protocol) {
21         if (protocol == null) {
22             throw new IllegalArgumentException("protocol == null");
23         }
24         this.protocol = protocol;
25     }
26 
27     public int getDefaultPort() {
28         return protocol.getDefaultPort();
29     }
30 
31     public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
32         if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
33             return protocol.export(invoker);
34         }
35         return new ListenerExporterWrapper<T>(protocol.export(invoker),
36                 Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
37                         .getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
38     }
39 
40     public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
41         if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
42             return protocol.refer(type, url);
43         }
44         return new ListenerInvokerWrapper<T>(protocol.refer(type, url),
45                 Collections.unmodifiableList(
46                         ExtensionLoader.getExtensionLoader(InvokerListener.class)
47                                 .getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
48     }
49 
50     public void destroy() {
51         protocol.destroy();
52     }
53 }

这里的方法不做讲解,等到了服务提供者暴露服务和服务消费者引用服务的时候再做讲解。

ProtocolFilterWrapper源码如下:

 1 package com.alibaba.dubbo.rpc.protocol;
 2 
 3 import com.alibaba.dubbo.common.Constants;
 4 import com.alibaba.dubbo.common.URL;
 5 import com.alibaba.dubbo.common.extension.ExtensionLoader;
 6 import com.alibaba.dubbo.rpc.Exporter;
 7 import com.alibaba.dubbo.rpc.Filter;
 8 import com.alibaba.dubbo.rpc.Invocation;
 9 import com.alibaba.dubbo.rpc.Invoker;
10 import com.alibaba.dubbo.rpc.Protocol;
11 import com.alibaba.dubbo.rpc.Result;
12 import com.alibaba.dubbo.rpc.RpcException;
13 
14 import java.util.List;
15 
16 public class ProtocolFilterWrapper implements Protocol {
17     private final Protocol protocol;
18 
19     public ProtocolFilterWrapper(Protocol protocol) {
20         if (protocol == null) {
21             throw new IllegalArgumentException("protocol == null");
22         }
23         this.protocol = protocol;
24     }
25 
26     private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
27         Invoker<T> last = invoker;
28         List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
29         if (filters.size() > 0) {
30             for (int i = filters.size() - 1; i >= 0; i--) {
31                 final Filter filter = filters.get(i);
32                 final Invoker<T> next = last;
33                 last = new Invoker<T>() {
34 
35                     public Class<T> getInterface() {
36                         return invoker.getInterface();
37                     }
38 
39                     public URL getUrl() {
40                         return invoker.getUrl();
41                     }
42 
43                     public boolean isAvailable() {
44                         return invoker.isAvailable();
45                     }
46 
47                     public Result invoke(Invocation invocation) throws RpcException {
48                         return filter.invoke(next, invocation);
49                     }
50 
51                     public void destroy() {
52                         invoker.destroy();
53                     }
54 
55                     @Override
56                     public String toString() {
57                         return invoker.toString();
58                     }
59                 };
60             }
61         }
62         return last;
63     }
64 
65     public int getDefaultPort() {
66         return protocol.getDefaultPort();
67     }
68 
69     public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
70         if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
71             return protocol.export(invoker);
72         }
73         return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
74     }
75 
76     public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
77         if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
78             return protocol.refer(type, url);
79         }
80         return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
81     }
82 
83     public void destroy() {
84         protocol.destroy();
85     }
86 }

这里的方法不做讲解,等到了服务提供者暴露服务和服务消费者引用服务的时候再做讲解。

最后返回的instance是ProtocolFilterWrapper对象,也就是说final Protocol dubboProtocol = loader.getExtension("dubbo");这句代码最后的dubboProtocol是ProtocolFilterWrapper实例。

 

至此,aop结束。 

5.1 javassist基本使用

假设要使用javassist创建一个类:

 1 package com.alibaba.dubbo.demo.test;
 2 
 3 public class Emp {
 4     //属性
 5     private int    account;
 6     private String name;
 7 
 8     //构造方法
 9     public Emp() {
10         this.account = 1;
11         this.name = "xiaona";
12     }
13 
14     //getter
15     public int getAccount() {
16         return account;
17     }
18 
19     //setter
20     public void setAccount(int account) {
21         this.account = account;
22     }
23 
24     public String getName() {
25         return name;
26     }
27 
28     public void setName(String name) {
29         this.name = name;
30     }
31 
32     //普通方法
33     public void commonMethod() {
34         System.out.println("haha");
35     }
36 }

该类包含属性/构造方法/getter/setter/普通方法。

使用javassist来创建类:

 1 package com.alibaba.dubbo.demo.test;
 2 
 3 import javassist.ClassPool;
 4 import javassist.CtClass;
 5 import javassist.CtConstructor;
 6 import javassist.CtField;
 7 import javassist.CtMethod;
 8 import javassist.CtNewMethod;
 9 import javassist.Modifier;
10 
11 import java.io.File;
12 import java.io.FileOutputStream;
13 
14 public class TestJavassitCompiler {
15     public static void main(String[] args) throws Exception {
16         ClassPool pool = ClassPool.getDefault();
17         CtClass ctClass = pool.makeClass("com.alibaba.dubbo.demo.test.Emp");
18         //添加属性:private String name
19         CtField nameField = new CtField(pool.getCtClass("java.lang.String"), "name", ctClass);
20         nameField.setModifiers(Modifier.PRIVATE);
21         ctClass.addField(nameField);
22         //添加属性:private int account
23         CtField accountField = new CtField(pool.getCtClass("int"), "account", ctClass);
24         accountField.setModifiers(Modifier.PRIVATE);
25         ctClass.addField(accountField);
26         //getter和setter
27         ctClass.addMethod(CtNewMethod.getter("getName", nameField));
28         ctClass.addMethod(CtNewMethod.setter("setName", nameField));
29         ctClass.addMethod(CtNewMethod.getter("getAccount", accountField));
30         ctClass.addMethod(CtNewMethod.setter("setAccount", accountField));
31         //创建构造器
32         CtConstructor ctConstructor = new CtConstructor(new CtClass[] {}, ctClass);
33         String body = new StringBuilder("{\nthis.account = 1;\nthis.name = \"xiaona\";\n}").toString();
34         ctConstructor.setBody(body);
35         ctClass.addConstructor(ctConstructor);
36         //普通方法
37         CtMethod ctMethod = new CtMethod(CtClass.voidType, "commonMethod", new CtClass[] {}, ctClass);
38         ctMethod.setModifiers(Modifier.PUBLIC);
39         ctMethod.setBody(new StringBuilder("{\n System.out.println(\"haha\"); \n}").toString());
40         ctClass.addMethod(ctMethod);
41 
42         Class<?> clazz = ctClass.toClass();
43         Object obj = clazz.newInstance();
44         obj.getClass().getMethod("commonMethod", new Class[] {}).invoke(obj, new Object[] {});//方法调用
45 
46         /**
47          * 将字节码输出到文件中
48          */
49         byte[] codeByteArray = ctClass.toBytecode();
50         FileOutputStream fos = new FileOutputStream(new File("/Users/jigangzhao/Desktop/Emp.class"));
51         fos.write(codeByteArray);
52         fos.close();
53     }
54 }

之后可以使用javap命令来看一下/Users/jigangzhao/Desktop/Emp.class文件。

关于javassit的API请查看:

https://github.com/jboss-javassist/javassist/wiki/Tutorial-1

5.2 dubbo-compiler源码解析

 
1         ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
2         final Protocol dubboProtocol = loader.getExtension("dubbo");
3         final Protocol adaptiveExtension = loader.getAdaptiveExtension();

2.2 dubbo-spi源码解析讲了第一句,在第四章 dubbo内核之aop源码解析讲了第二句,本章来讲最后一句。

getAdaptiveExtension()层级结构:

1 ExtensionLoader<T>.getAdaptiveExtension()
2 --createAdaptiveExtension()
3 ----injectExtension(getAdaptiveExtensionClass())
4 ------getAdaptiveExtensionClass()
5 --------getExtensionClasses()//从spi文件中查找实现类上具有@Adaptive注解的类
6 ----------loadExtensionClasses()
7 ------------loadFile(Map<String, Class<?>> extensionClasses, String dir)
8 --------createAdaptiveExtensionClass()//如果从spi文件中没有找到实现类上具有@Adaptive注解的类,则动态创建类

这里最后执行到了createAdaptiveExtensionClass()方法。

1     private Class<?> createAdaptiveExtensionClass() {
2         String code = createAdaptiveExtensionClassCode();
3         ClassLoader classLoader = findClassLoader();
4         com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
5         return compiler.compile(code, classLoader);
6     }

 

一 构造代码串

createAdaptiveExtensionClassCode()方法中会判断如果一个类中没有@Adaptive注解的方法,则直接抛出IllegalStateException异常;否则,会为有@Adaptive注解的方法构造代码,而没有@Adaptive注解的方法直接抛出UnsupportedOperationException异常。

构造出的结果为:

 1 package com.alibaba.dubbo.rpc;
 2 
 3 import com.alibaba.dubbo.common.extension.ExtensionLoader;
 4 
 5 public class Protocol$Adaptive implements com.alibaba.dubbo.rpc.Protocol {
 6     public void destroy() {
 7         throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
 8     }
 9     public int getDefaultPort() {
10         throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
11     }
12     public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws com.alibaba.dubbo.rpc.RpcException {
13         if (arg1 == null)
14             throw new IllegalArgumentException("url == null");
15         com.alibaba.dubbo.common.URL url = arg1;
16         String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
17         if(extName == null)
18             throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
19         com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
20         return extension.refer(arg0, arg1);
21     }
22     public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
23         if (arg0 == null)
24             throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
25         if (arg0.getUrl() == null)
26             throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
27         com.alibaba.dubbo.common.URL url = arg0.getUrl();
28         String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
29         if(extName == null)
30             throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
31         com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
32         return extension.export(arg0);
33     }
34 }

说明:

  • 该生成类在dubbo2.5.3中export和refer方法声明处的异常抛出是错的(在dubbo2.5.4改正了);
  • 类名在dubbo2.5.4之前(包含2.5.4)也是错的Protocol$Adpative,dubbo2.5.5改正了。

 

二 获取Compiler装饰类

com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();

先看一下com.alibaba.dubbo.common.compiler.Compiler接口:

1 @SPI("javassist")
2 public interface Compiler {
3     Class<?> compile(String code, ClassLoader classLoader);
4 }

@SPI的默认值为javassist,根据上一节的经验,默认获取的Compiler接口的实现类将是META-INF/dubbo/internal/com.alibaba.dubbo.common.compiler.Compiler文件中的key为javassit的实现类。文件内容如下:

1 adaptive=com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler
2 jdk=com.alibaba.dubbo.common.compiler.support.JdkCompiler
3 javassist=com.alibaba.dubbo.common.compiler.support.JavassistCompiler

根据上一节对ExtensionFactory的getAdaptiveExtension()的讲解,我们最终获取到的Compiler的AdaptiveExtension将是com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler。

来看源码,首先是获取ExtensionLoader<com.alibaba.dubbo.common.compiler.Compiler> loader,最终的loader包含如下属性:

  • Class<?> type = interface com.alibaba.dubbo.common.compiler.Compiler
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
    • factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]

之后,是loader.getAdaptiveExtension()。

在该方法中,首先会调用createAdaptiveExtension()创建实例,之后放入缓存,然后返回。

 1     private T createAdaptiveExtension() {
 2         try {
 3             return injectExtension((T) getAdaptiveExtensionClass().newInstance());
 4         } catch (Exception e) {
 5             throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(),
 6                 e);
 7         }
 8     }
 9 
10     private Class<?> getAdaptiveExtensionClass() {
11         /**
12          * 获取ExtensionClasses和适配类
13          * 其中适配类cachedAdaptiveClass如果不存在,则需要使用createAdaptiveExtensionClass()进行创建.
14          */
15         getExtensionClasses();
16         if (cachedAdaptiveClass != null) {
17             return cachedAdaptiveClass;
18         }
19         return cachedAdaptiveClass = createAdaptiveExtensionClass();
20     }

在createAdaptiveExtension()中首先会调用getAdaptiveExtensionClass()获取ExtensionClasses和修饰类,之后将修饰类返回。根据META-INF/dubbo/internal/com.alibaba.dubbo.common.compiler.Compiler文件的内容,最后返回

  • ExtensionClasses
    • "jdk" -> "class com.alibaba.dubbo.common.compiler.support.JdkCompiler"
    • "javassist" -> "class com.alibaba.dubbo.common.compiler.support.JavassistCompiler"
  • cachedAdaptiveClass=class com.alibaba.dubbo.common.compiler.support.AdaptiveCompiler

之后调用AdaptiveCompiler的无参构造器创建AdaptiveCompiler对象实例,然后执行injectExtension(T instance)(这里没起作用)为AdaptiveCompiler对象实例注入相应的属性(AdaptiveCompiler必须提供相应的setter方法),最后返回AdaptiveCompiler对象实例。

 

三 编译代码并加载为Class<?>对象

创建好AdaptiveCompiler对象实例之后,然后执行下面的方法。

Class<?> compile(String code, ClassLoader classLoader)

看一下AdaptiveCompiler全部源码:

 1 @Adaptive
 2 public class AdaptiveCompiler implements Compiler {
 3     private static volatile String DEFAULT_COMPILER;//默认的编译器的名字
 4 
 5     public static void setDefaultCompiler(String compiler) {
 6         DEFAULT_COMPILER = compiler;
 7     }
 8 
 9     /**
10      * 典型的动态代理,在代理类中,存放着真实对象,使用真实对象执行相应的方法
11      */
12     public Class<?> compile(String code, ClassLoader classLoader) {
13         Compiler compiler;
14         ExtensionLoader<Compiler> loader = ExtensionLoader.getExtensionLoader(Compiler.class);
15         String name = DEFAULT_COMPILER; // copy reference
16         if (name != null && name.length() > 0) {
17             compiler = loader.getExtension(name);//获取名字为name的实现类的实例,在获取的过程中会完成IOC和AOP
18         } else {
19             compiler = loader.getDefaultExtension();//获取默认的JavassitCompiler,调用getExtension(cachedDefaultName)
20         }
21         return compiler.compile(code, classLoader);//根据获取到的实现类compiler实例,来执行真正的动态生成类的代码
22     }
23 }

这里执行的是compiler = loader.getDefaultExtension(),该方法不说了,就是调用了getExtension(cachedDefaultName)生成一个JavassistCompiler的实例。之后就是执行JavassistCompiler的compile(String code, ClassLoader classLoader)方法。

 1 package com.alibaba.dubbo.common.compiler.support;
 2 
 3 import com.alibaba.dubbo.common.compiler.Compiler;
 4 import com.alibaba.dubbo.common.utils.ClassHelper;
 5 
 6 import java.util.regex.Matcher;
 7 import java.util.regex.Pattern;
 8 
 9 /**
10  * Abstract compiler. (SPI, Prototype, ThreadSafe)
11  */
12 public abstract class AbstractCompiler implements Compiler {
13     private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\\s+([$_a-zA-Z][$_a-zA-Z0-9\\.]*);");
14     private static final Pattern CLASS_PATTERN = Pattern.compile("class\\s+([$_a-zA-Z][$_a-zA-Z0-9]*)\\s+");
15 
16     /**
17      * 1 根据正则表达式从code中获取包名和类名,组成全类名
18      * 2 根据全类名使用Class.forName创建Class<?>,如果该类在jvm中存在,则成功,否则抛出ClassNotFoundException,
19      *   执行doCompile方法。
20      */
21     public Class<?> compile(String code, ClassLoader classLoader) {
22         code = code.trim();
23         Matcher matcher = PACKAGE_PATTERN.matcher(code);
24         String pkg;
25         if (matcher.find()) {
26             pkg = matcher.group(1);
27         } else {
28             pkg = "";
29         }
30         matcher = CLASS_PATTERN.matcher(code);
31         String cls;
32         if (matcher.find()) {
33             cls = matcher.group(1);
34         } else {
35             throw new IllegalArgumentException("No such class name in " + code);
36         }
37         String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls;
38         try {
39             return Class.forName(className, true, ClassHelper.getCallerClassLoader(getClass()));
40         } catch (ClassNotFoundException e) {
41             if (!code.endsWith("}")) {
42                 throw new IllegalStateException("The java code not endsWith \"}\", code: \n" + code + "\n");
43             }
44             try {
45                 return doCompile(className, code);
46             } catch (RuntimeException t) {
47                 throw t;
48             } catch (Throwable t) {
49                 throw new IllegalStateException("Failed to compile class, cause: " + t.getMessage() + ", class: " + className + ", code: \n" + code + "\n, stack: " + ClassUtils.toString(t));
50             }
51         }
52     }
53 
54     protected abstract Class<?> doCompile(String name, String source) throws Throwable;
55 }

该方法会执行JavassistCompiler的Class<?> doCompile(String name, String source)方法了,在该方法中,使用正则表达式对传入的源码解析成属性方法等,并使用javassist的API创建Class<?>。

最后,该final Protocol adaptiveExtension = loader.getAdaptiveExtension();代码返回的adaptiveExtension = Protocol$Adaptive实例。

总结(再啰嗦一遍):

  • ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()最终返回的是:AdaptiveExtensionFactory实例,其属性factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]
  • 不管是获取哪一个SPI接口(除了ExtensionFactory.接口)的ExtensionLoader,最终一定会有一个objectFactory=上述的AdaptiveExtensionFactory实例
  • getAdaptiveExtension():作用就是获取一个装饰类或动态代理类的实例, 如果有@Adaptive注解的类,则直接返回该类的实例,否则返回一个动态代理类的实例(例如Protocol$Adaptive的实例),之后完成属性注入(dubbo-IOC),最后返回实例。
  • getExtension(String key):作用就是从extensionClasses(即指定SPI接口的没有@Adaptive的实现类)获取指定key的extensionClass,并且实例化,之后完成属性注入(dubbo-IOC),再之后完成dubbo-AOP,最后返回实例。

 

posted @ 2022-05-21 15:09  hanease  阅读(110)  评论(0编辑  收藏  举报