Seata源码解析2 —— SPI扩展

本文介绍了Seata的SPI扩展点实现,不同于依赖Spring,Seata自身构建了一套类管理机制。文章详细讲解了如何使用Seata的SPI,包括接口实现类的注解和加载流程,并总结了其相对简单的扩展点设计。对于熟悉Spring但不熟悉Seata SPI的开发者,这是一个很好的学习资源。
摘要由CSDN通过智能技术生成
前言

我们平时使用Spring时,由Spring来管理类,Seata没有依赖Spring,因此它自己做了一套SPI机制,用于类的管理。

由于Seata里面一个接口有多个实现类,如配置中心就支持consul、etcd3、nacos等。这些实现类都继承了同一个接口,在运行时获取某一个实现类,就需要使用到SPI扩展点了。

使用方式

EnhancedServiceLoader类中有load方法和loadFile方法,load方法是包装loadFile方法实现的,如:

public static <S> S load(Class<S> service, ClassLoader loader) throws EnhancedServiceNotFoundException {
   
    return loadFile(service, null, loader);
}

private static <S> S loadFile(Class<S> service, String activateName, ClassLoader loader) {
   
    //不同参数的load方法,都是包装方法,最终调用的都是loadFile方法
    return loadFile(service, activateName, loader, null, null);
}

在每个接口的实现类上,都会有一个@LoadLevel注解,以FrenchHello实现类为例:

//定义一个hello接口
public interface Hello {
   
    String say();
}

//实现类使用LoadLevel注解,有两个参数,name标识实现类的名称,order表示实现类的顺序
@LoadLevel(name = "FrenchHello", order = 2)
public class FrenchHello implements Hello {
   
    @Override
    public String say() {
   
        return "Bonjour";
    }
}

我们可以这样使用:

Hello load = EnhancedServiceLoader.load(Hello.class, Hello.class.getClassLoader());
load.say()
源码解析

整个源码的总体流程可以总结为:

1.第一次初始化时,解析默认目录下的SPI文件,并加载Class、根据注解中的order排序,这些Class是全量的,会被缓存。

如果指定了activateName,则加载activateName目录下的SPI文件中配置的类。这些Class不是全量的,也不会被缓存。

2.如果有多个符合的扩展点,并且没有指定要取哪一个,则默认取order最大的那个。

3.初始化对应的扩展点Class。

1基础属性:

//SPI的默认加载路径
private static final String SERVICES_DIRECTORY = "META-INF/services/";
private static final String SEATA_DIRECTORY = "META-INF/seata/";
//用于缓存SPI类的ConcurrentHashMap
@SuppressWarnings("rawtypes")
private static Map<Class, List<Class>> providers = new ConcurrentHashMap<Class, List<Class>>();

2指定加载某个扩展点:

load方法们,参数不同,但都是调用了loadFile方法。

public static <S> S load(Class<S> service, ClassLoader loader) throws EnhancedServiceNotFoundException {
   
    //activateName参数默认为null,用户指定ClassLoader
    return loadFile(service, null, loader);
}

public static <S> S load(Class<S> service) throws EnhancedServiceNotFoundException {
   
   //用户不需要指定ClassLoader,直接通过EnhancedServiceLoader.class.getClassLoader()获取
    return loadFile(service, null, findClassLoader());
}

public static <S> S lo
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值