目录
- 原理概述
- 为什么设计@Adaptive注解
- dubbo源码中哪些地方什么时候使用到了,具体如何体现
- @Adaptive扩展加载过程源码分析
- 总结
原理概述
首先看以下官网的关于自适应扩展的描述:
在 Dubbo 中,很多拓展都是通过 SPI 机制进行加载的,比如 Protocol、Cluster、LoadBalance 等。有时,有些拓展并不想在框架启动阶段被加载,而是希望在拓展方法被调用时,根据运行时参数进行加载。这听起来有些矛盾。拓展未被加载,那么拓展方法就无法被调用(静态方法除外)。拓展方法未被调用,拓展就无法被加载。对于这个矛盾的问题,Dubbo 通过自适应拓展机制很好的解决了。自适应拓展机制的实现逻辑比较复杂,首先 Dubbo 会为拓展接口生成具有代理功能的代码。然后通过 javassist 或 jdk 编译这段代码,得到 Class 类。最后再通过反射创建代理类,整个过程比较复杂。
好像还是有点抽象,首先回顾下dubbo的SPI是什么:spi是一种扩展机制,目的就是为了获取一个对象。通过ExtensionLoader.getExtension(String name)获取,通过ExtensionLoader.getAdaptiveExtension()获取扩展类,这个扩展类的自适应具体时如何适应的呢,继续往下看
看下@Adaptive注解的源码定义,可以看出这个注解可以用在方法上和类上
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Adaptive {
String[] value() default {};
}
为什么设计@Adaptive注解
设计Adaptive注解是为了区分人工编码的和动态生成的类
注解在类上时,表示扩展的逻辑有人工编码完成,不需要生成动态代理类(对应的java文件已经存在项目源码中);在 Dubbo 中,仅有两个类被 Adaptive 注解了,分别是 AdaptiveCompiler 和 AdaptiveExtensionFactory;AdaptiveCompiler 只有两个实现类JavassistCompiler和JdkCompiler;AdaptiveExtensionFactory只有两个实现类,SpiExtensionFactory和SpringExtensionFactory.
注解在接口方法上,表示表示扩展的逻辑有框架自动生成(对应的java文件在启动后按需要动态拼接字符串生成,编译加载);例如Protocol接口,实现类有DubboProtocol,InjvmProtocol, HttpProtcol 等等
后面会以AdaptiveCompiler和Protocol为例来分析扩展的加载过程
dubbo源码中哪些地方什么时候使用到了,具体如何体现
下面从最基本的xml配置文件开始分析:
<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
从spring.handlers得知解析DubboNamespaceHandler
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
}
public void init() {
registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinit