重要的网址:
- dubbo的github:https://github.com/alibaba/dubbo
- dubbo官网:http://dubbo.io/
- dubbo使用者手册:https://dubbo.gitbooks.io/dubbo-user-book/
- dubbo管理者手册:https://dubbo.gitbooks.io/dubbo-admin-book/
- dubbo开发者手册:https://dubbo.gitbooks.io/dubbo-dev-book/
第一个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×tamp=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×tamp=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,最后返回实例。