Seata SPI 机制

7 篇文章 1 订阅

SPI 全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。

JAVA SPI 机制本文不做讲解,自行了解。

SEATA SPI

Seata 的 SPI 机制由类 EnhancedServiceLoader 提供 , 翻译一下就是: 增强服务载入器

Seata 的SPI 是一个基础模块 ,对于Seata框架起着至关重要的作用, 熟悉了 Java SPI 机制后,Seata 就更容易理解,
只是相对于Java SPI 做了一些增强, 例如可以通过名字,可以存在构造参数

大致上可以分为以下三个维度加载需要的服务

  1. load 通过 Class 载入一个默认服务
  2. load 通过 Class 和名字载入一个服务
  3. loadAll 通过 Class 载入一组服务

Seata SPI 兼容了 JAVA SPI, 首先从目录 META-INF/services/ 加载服务,然后在从目录 META-INF/seata/ 加载服务。
虽然这么说,但是 seata 默认的扩展都还是放在目录 META-INF/services/ 下面。例如: Seata序列化扩展的位置:
META-INF/services/io.seata.core.serializer.Serializer, 内容: io.seata.serializer.seata.SeataSerializer

Seata SPI的每个扩展类都是有名字的,但是不放在配置文件中,而是在实现类上面会有注解 @LoadLevel,例如:

@LoadLevel(name = "SEATA")
public class SeataSerializer implements Serializer {
} 

Seata SPI 机制和 Dubbo 的 SPI 非常相似, 这是对 Dubbo SPI 的一种肯定。
IOC部分简化了, Holder模式, 单例加载的双重锁都是值得学习的地方。

载入级别

LoadLevel 的声明如下:

public @interface LoadLevel {
    /**
     * 名字, 需要唯一
     */
    String name();

    /**
     * Order int.
     * loadAll 方法需要这个字段的值,对加载到的 ExtensionDefinition 进行排序
     * 对于需要获得多个实现进行排序的场景,通常用于责任链模式。
     * 在Seata 中, 在拦截器 StateHandlerInterceptor 的实现中 Saga 拦截器将优先于其他的拦截器
     */
    int order() default 0;

    /**
     * Scope enum. 可以选择单例(SINGLETON),原型(PROTOTYPE)
     */
    Scope scope() default Scope.SINGLETON;
}

通过Class加载一个服务

这是通过指定的接口加载默认实现。 默认值为: 排在最后面的实现。

 public static <S> S load(Class<S> service, ClassLoader loader) throws EnhancedServiceNotFoundException {
        return InnerEnhancedServiceLoader.getServiceLoader(service).load(loader);
    }
    public static <S> S load(Class<S> service) throws EnhancedServiceNotFoundException {
        return InnerEnhancedServiceLoader.getServiceLoader(service).load(findClassLoader());
    }

通过Class和名字加载一个服务

首先会加载指定接口的所有Class,
然后根据名字加载具体实现的实例

// 通过类 EnhancedServiceLoader  的 ClassLoader 载入
    public static <S> S load(Class<S> service, String activateName) throws EnhancedServiceNotFoundException {
        return InnerEnhancedServiceLoader.getServiceLoader(service).load(activateName, findClassLoader());
    }
    // 外部可以指定ClassLoader的载入
    public static <S> S load(Class<S> service, String activateName, ClassLoader loader)
            throws EnhancedServiceNotFoundException {
        return InnerEnhancedServiceLoader.getServiceLoader(service).load(activateName, loader);
    }
    // 特殊支持, 支持构造参数初始化
    public static <S> S load(Class<S> service, String activateName, Object[] args)
            throws EnhancedServiceNotFoundException {
        return InnerEnhancedServiceLoader.getServiceLoader(service).load(activateName, args, findClassLoader());
    }
    // 特殊支持, 支持构造参数初始化,  可以指定参数类型
    public static <S> S load(Class<S> service, String activateName, Class[] argsType, Object[] args)
            throws EnhancedServiceNotFoundException {
        return InnerEnhancedServiceLoader.getServiceLoader(service).load(activateName, argsType, args, findClassLoader());
    }

通过 Class 载入一组服务

// 通过指定接口,载入所有实例
 public static <S> List<S> loadAll(Class<S> service) {
        return InnerEnhancedServiceLoader.getServiceLoader(service).loadAll(findClassLoader());
    }
// 通过指定接口和构造参数信息, 载入所有实例
    public static <S> List<S> loadAll(Class<S> service, Class[] argsType, Object[] args) {
        return InnerEnhancedServiceLoader.getServiceLoader(service).loadAll(argsType, args, findClassLoader());
    }

InnerEnhancedServiceLoader

内部增强服务载入器, 前面载入的方法都是通过 InnerEnhancedServiceLoader 类实现的。
那么 InnerEnhancedServiceLoader 有什么用? 为什么要存在呢?

InnerEnhancedServiceLoader 的作用:

  1. 提供了 Class 到 InnerEnhancedServiceLoader 的缓存
  2. 提供了 Class 到 ExtensionDefinition 的缓存
  3. 提供了 扩展名 到 ExtensionDefinition 的缓存
  4. 提供了 ExtensionDefinition 到 接口实例 的缓存

总体来看, 它避免了多次载入同一个接口的扩展时, 不必要的载入。

然而它还是一个小型的IOC, 在创建对象的时候支持构造函数注入,
获取实例时, 如果是PROTOTYPE类型的, 每次获取都会创建新的实例。
而且还支持初始化, 对于实现了接口 Initialize 的实现类, 创建对象完成后, 会调用实例的 init() 方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
seata 1.6.0 是一种开源的分布式事务解决方案,它旨在简化分布式事务的管理和开发。seata 1.6.0 支持高可用的分布式事务处理,可以确保分布式系统的数据一致性。 seata 1.6.0 的主要特性包括三个方面:事务办理,分布式锁,跨分布式事务通信。 在事务办理方面,seata 1.6.0 提供了全局事务和本地事务的支持。通过全局事务管理器,可以协调参与分布式事务的各个服务,确保事务的一致性。本地事务管理器则负责具体的事务处理。seata 1.6.0 还支持分布式事务的嵌套,可以在一个事务中包含多个子事务。这样,可以更好地控制事务的执行流程。 分布式锁也是 seata 1.6.0 的一个重要特性。通过分布式锁的机制,可以确保在多个服务之间对共享资源的访问是安全和可靠的。seata 1.6.0 提供了多种分布式锁的实现,如数据库锁、Redis 锁等。这些锁机制可以防止多个服务之间的数据竞争问题,并确保数据的一致性。 seata 1.6.0 还提供了跨分布式事务通信的能力。在分布式系统中,各个服务之间需要相互通信,以便协调事务的执行。seata 1.6.0 使用了可靠消息传递的机制,确保消息的可靠传递和处理。通过这种方式,可以保证分布式事务的正确执行。 总的来说,seata 1.6.0 是一个功能强大的分布式事务管理解决方案。它通过提供事务办理、分布式锁和跨分布式事务通信等功能,简化了分布式系统的开发和管理,提高了系统的可靠性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值