Dubbo系列之自定义SPI协议拓展点_codain的博客-CSDN博客Dubbo系列之自定义SPI协议拓展点https://blog.csdn.net/qq_38377525/article/details/123002941为了这个文章的内容,大家可以充分吸收,首先要确保大家是了解过上面链接中的章节内容,如果不了解或者不清楚的,个人建议要先搞懂上面的链接,然后再接着看本篇章
自适应(Adaptive)拓展点,简单来说就是能够根据上下文需求动态匹配一个拓展类,调用代码如下
ExtensionLoader.getExtensionLoader(class).getAdaptiveExtension();
自适应拓展点可以通过注解@Adaptive来声明实现,此注解有两种使用方式
1、注册定义在类上面,标识该类为自适应拓展类
@Adaptive public class MysqlDriver implement Driver{//此处代码省略... }
MysqlDriver在这里就是一个自适应拓展类,通过ExtensionLoader.getExtensionLoader(Driver.class).getAdaptiveExtension();可以返回MysqlDriver类的实例
2、定义在方法上,程序会通过动态代理的方式为其生成一个动态的字节码,进行自适应匹配
@SPI public interface Driver{@AdaptiveString connection(String name); }
上述代码意味着存在一个自适应方法,获得一个自适应拓展点代码为:Driver driver=ExtensionLoader.getExtensionLoader(Driver.class).getAdaptiveExtension();
不管@Adaptive是在类上还是方法上,我们都要分析一下源码,看看是怎么实现自适应的,我们从ExtensionLoader.getExtensionLoader(class).getAdaptiveExtension();代码入手
1、getAdaptiveExtension()
public T getAdaptiveExtension() {//获取缓存中所有拓展点实例Object instance = this.cachedAdaptiveInstance.get();if (instance == null) {if (this.createAdaptiveInstanceError != null) {throw new IllegalStateException("Failed to create adaptive instance: " + this.createAdaptiveInstanceError.toString(), this.createAdaptiveInstanceError);}//创建自适应拓展点,并缓存Holder var2 = this.cachedAdaptiveInstance;synchronized(this.cachedAdaptiveInstance) {instance = this.cachedAdaptiveInstance.get();if (instance == null) {try {//创建自适应拓展点instance = this.createAdaptiveExtension();this.cachedAdaptiveInstance.set(instance);} catch (Throwable var5) {this.createAdaptiveInstanceError = var5;throw new IllegalStateException("Failed to create adaptive instance: " + var5.toString(), var5);}}}}return instance; }
看一下这个代码,是不是和最上面提供的链接逻辑差不多?他存在一个createAdaptiveExtension()方法,这个方法和Dubbo纯SPI的createExtension()方法是一样的逻辑:先获得拓展点实例,再完成依赖注入
2、createAdaptiveExtension()
private T createAdaptiveExtension() {try {//下一段代码分析:getAdaptiveExtensionClass()return this.injectExtension(this.getAdaptiveExtensionClass().newInstance());} catch (Exception var2) {throw new IllegalStateException("Can't create adaptive extension " + this.type + ", cause: " + var2.getMessage(), var2);}}
3、getAdaptiveExtensionClass()
private Class<?> getAdaptiveExtensionClass() {//获取入参的所有拓展点,缓存在一个集合中this.getExtensionClasses();//如果获取的为null,需要调用createAdaptiveExtensionClass创建return this.cachedAdaptiveClass != null ? this.cachedAdaptiveClass : (this.cachedAdaptiveClass = this.createAdaptiveExtensionClass());}
4、createAdaptiveExtensionClass()
private Class<?> createAdaptiveExtensionClass() {//返回一个动态拼接的字符串String code = (new AdaptiveClassCodeGenerator(this.type, this.cachedDefaultName)).generate();ClassLoader classLoader = findClassLoader();//获取Conpiler拓展点Compiler compiler = (Compiler)getExtensionLoader(Compiler.class).getAdaptiveExtension();//动态编译return compiler.compile(code, classLoader);}
5、调用Dubbo自适应实现类Protocol$Adaptive,采用的是适配器模式,然后根据上下文信息自动适配到相应的协议拓展点来完成服务的加载和发布
附上一个在写这个文章很早之前的一个demo样例链接
dubbo-spi: dubbo的spi机制讲解https://gitee.com/IT_CB/dubbo-spi/