专注于Java、Golang、软件架构、项目管理

Back

Dubbo 为了更好地达到 OCP 原则(即“对扩展开放,对修改封闭”的原则),采用了“微内核+插件”的架构。那什么是微内核架构呢?微内核架构也被称为插件化架构(Plug-in Architecture),这是一种面向功能进行拆分的可扩展性架构。内核功能是比较稳定的,只负责管理插件的生命周期,不会因为系统功能的扩展而不断进行修改。功能上的扩展全部封装到插件之中,插件模块是独立存在的模块,包含特定的功能,能拓展内核系统的功能。

微内核常见的方式有SPI(Service Provider Interface)、Factory、IOC、OSGI等。dubbo采用的是SPI,参考了JDK原生的SPI,并进行了优化和功能增强。

JDK SPI#

需要在Classpath 下的 META-INF/services/目录创建一个以接口名命名的文件。mysql的driver就是使用的此方式,spring中相关框架也有相关应用

在项目的 resources/META-INF/services 目录下添加一个名为 com.xxx.Log 的文件,这是 JDK SPI 需要读取的配置文件,具体内容如下:

com.xxx.impl.Log4j 
com.xxx.impl.Logback 
ini

使用方法如下

public class Main { 
    public static void main(String[] args) { 
        ServiceLoader<Log> serviceLoader =  
                ServiceLoader.load(Log.class); 
        Iterator<Log> iterator = serviceLoader.iterator(); 
        while (iterator.hasNext()) { 
            Log log = iterator.next(); 
            log.log("JDK SPI");  
        } 
    } 
} 
java

JDK SPI缺点#

所有的实现类都会被加载并初始化,如果没有使用就会有资源的浪费。

dubbo SPI#

dubbo SPI将配置文件改为kv形式,在需要用到的时候再进行加载并初始化,并且使用的时候也不需要遍历SPI所有的接口。

@SPI注解#

dubbo中某个接口被@SPI注解修饰时,就表示该接口是dubbo扩展接口

@SPI(value = "dubbo", scope = ExtensionScope.FRAMEWORK)
public interface Protocol {
//忽略其内容
}
java

@SPI 注解的 value 值指定了默认的扩展名称,例如,在通过 Dubbo SPI 加载 Protocol 接口实现时,如果没有明确指定扩展名,则默认会将 @SPI 注解的 value 值作为扩展名,即加载 dubbo 这个扩展名对应的 org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol 这个扩展实现类

Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getDefaultExtension();//与下面等价
//Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("dubbo");
java

ExtensionLoader.getExtension()方法。

@Adaptive 注解与适配器#

@Adaptive 注解用来实现dubbo的适配器功能。

Adaptive 注解在类上的情况很少,在 Dubbo 中,仅有两个类被 Adaptive 注解了,分别是 AdaptiveCompiler 和 AdaptiveExtensionFactory。此种情况,表示拓展的加载逻辑由人工编码完成。

加到方法上,较常用。表示拓展的加载逻辑需由框架自动生成,dubbo借助了javaassist框架,进行相关代码生成。

@Activate注解与自动激活特性#

使用方法

URL url = URL.valueOf("test://localhost/test");
List<ActivateExt1> list = getExtensionLoader(ActivateExt1.class)
    .getActivateExtension(url, new String[]{}, "order");
java

总结#

dubbo中无非就是用了以上SPI的功能,来实现相关的功能。理解了以上代码,再逐个去看dubbo中的相关代码。在需要扩展或者修改的时候,就可以通过SPI来实现。我之前实现了一个按id定向loadbalance的扩展,就是参考了LoadBalance接口源码,进行了相关扩展。

在使用**@DubboReference@DubboService**,在相关的注解配置中,使用自己扩展的功能即可。如下

@DubboReference(interfaceClass = Admin.class,loadbalance = "myhash")
   private Admin admin;
java