目录
1 前提必备知识
2 术语定义
3 自适应扩展机制的特点
4 扩展点实践
4.1 用户自定义自适应扩展
4.2 dubbo生成自适应扩展
4 自适应扩展类的用途
具体的使用和原理就不说了,网上有人写的挺好的了。
可以参考:
Dubbo SPI之自适应扩展机制 @Adaptive - 简书
我们先统一下本文使用的术语(个人观点,有问题欢迎讨论):
1)扩展点(就是接口):一个接口,在dubbo中使用该接口,业务人员可以动态的替换相应的扩展。
2)扩展(就是实现类):扩展点对应的实现类。一个扩展点可以有多个扩展。dubbo中通过URL+自适应扩展来实现根据参数,动态选择扩展。
在本文中,扩展点等价于接口,扩展等价于实现类。
看过源码后,想自己总结关于自适应扩展机制的特点:
1 自适应扩展点,一个接口只能对应一个自适应扩展,其他的扩展都是实现业务功能的扩展,该类只会有一个对象被缓存到ExtensionLoader中。可以参考ExtensionLoader源码的属性cachedAdaptiveClass、cachedAdaptiveInstance。
2 ExtensionLoader允许我们自定义自适应扩展,只要在一个实现类上加上@Adaptive注解即可。参考AdaptiveCompiler类。
3 如果我们自己不定义,ExtensionLoader可以帮我们生成一个接口(该接口的方法上需要添加@Adaptive注解)的对应实现类。
我们在一个扩展上面加上@Adaptive注解,该扩展会成为自适应扩展。
4.1.1 项目例子概述
HelloService一个接口,该接口有3个实现(两个业务相关的实现,一个自适应实现)。一个dubbo扩展配置文件,一个程序启动入口类。
HelloService接口
package org.example.test.exAdaptive;
import org.apache.dubbo.common.extension.SPI;
@SPI("father")
public interface HelloService {
String sayHello(String name);
}
两个业务实现类,FatherHelloServiceImpl、MotherHelloServiceImpl。
package org.example.test.exAdaptive;
public class FatherHelloServiceImpl implements HelloService{
@Override
public String sayHello(String name) {
return "Father say hello to " + name;
}
}
--------------------------------------
package org.example.test.exAdaptive;
public class MotherHelloServiceImpl implements HelloService{
@Override
public String sayHello(String name) {
return "Mather say hello to " + name;
}
}
自适应扩展类,注意@Adaptive注解加在类上来。
package org.example.test.exAdaptive;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionLoader;
/**
* @author lihe49
* @version 1.0
*/
@Adaptive
public class AdaptiveHelloServiceImpl implements HelloService{
@Override
public String sayHello(String name) {
ExtensionLoader loader = ExtensionLoader.getExtensionLoader(HelloService.class);
HelloService helloService;
if (name.equals("A")){
helloService = loader.getExtension("father");
} else {
helloService = loader.getExtension("mother");
}
return helloService.sayHello(name);
}
}
dubbo扩展配置文件,org.example.test.exAdaptive.HelloService文件
father=org.example.test.exAdaptive.FatherHelloServiceImpl
mother=org.example.test.exAdaptive.MotherHelloServiceImpl
adaptive=org.example.test.exAdaptive.AdaptiveHelloServiceImpl
程序启动入口文件,DubboSPI_AdaptiveTest类
package org.example.test.exAdaptive;
import org.apache.dubbo.common.extension.ExtensionLoader;
import java.util.Set;
public class DubboSPI_AdaptiveTest {
public static void main(String[] args) {
ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(HelloService.class);
Set supportedExtensions = extensionLoader.getSupportedExtensions();
System.out.println("HelloService的扩展为: " + supportedExtensions);
HelloService adaptiveExtension = extensionLoader.getAdaptiveExtension();
System.out.println("自适应类名为: " + adaptiveExtension);
}
}
运行结果
需要注意两点:
1)虽然有3个实现类,但是只有两个扩展。
2)自适应扩展的类名是真是的类名。
自适应扩展只能有一个有效。定义2个,最后一个生效。感兴趣的同学可以自己测试一下。
dubbo生成自适应扩展,需要在接口的方法上添加@Adaptive注解。
这个网上例子比较多。可以参考这篇文章的demo部分。
Dubbo插件扩展机制(@Adaptive) - StrangerIt - 博客园
自适应扩展类用途是什么呢?
答:
1)可以通过URL参数动态选择扩展。主要是dubbo自动生成扩展方式。
2)dubbo扩展类自动注入属性的时候,注入的属性实例是自适应扩展实例。