Seata spi实现类源码解析

Seata-common模块,EnhancedServiceLoader类解析

1. 简单介绍下  java spi思想

  • 为某个接口寻找服务实现的机制
  • 解耦(接口调用与服务提供者解耦)
  • 基于接口编程

2. Seata spi核心类EnhancedServiceLoader分析

使用例子:

定义接口类 com.test.Hello 
实现类A com.test.AHello
实现类B com.test.BHello
在resources目录下新建META-INF/services目录,并添加接口全路径名文件com.test.Hello 文件中写入实现类全路径名

图片

调用EnhancedServiceLoader.load(Hello.class) 获取实现类。

2.1最重要的几个方法解析

//加载所有的扩展类loadAllExtensionClass(loader);//获取默认扩展类ExtensionDefinition defaultExtensionDefinition = getDefaultExtensionDefinition();//获取指定的扩展类ExtensionDefinition cachedExtensionDefinition = getCachedExtensionDefinition(activateName);//获取扩展类实例getExtensionInstance(cachedExtensionDefinition, loader, argTypes, args);

2.2加载默认扩展类

private S loadExtension(ClassLoader loader, Class[] argTypes, Object[] args) { try { loadAllExtensionClass(loader); //默认获取list最后一个元素,list已按order值排序 ExtensionDefinition defaultExtensionDefinition = getDefaultExtensionDefinition(); //对扩展类实例化 return getExtensionInstance(defaultExtensionDefinition, loader, argTypes, args); } catch (Throwable e) { if (e instanceof EnhancedServiceNotFoundException) { throw (EnhancedServiceNotFoundException)e; } else { throw new EnhancedServiceNotFoundException( "not found service provider for : " + type.getName() + " caused by " + ExceptionUtils .getFullStackTrace(e)); } } }

2.3 加载扩展类并缓存

//加载所有的扩展类private List<Class> loadAllExtensionClass(ClassLoader loader) { List<ExtensionDefinition> definitions = definitionsHolder.get(); if (definitions == null) { synchronized (definitionsHolder) { definitions = definitionsHolder.get(); if (definitions == null) { //类加载器查找所有定义的扩展类 definitions = findAllExtensionDefinition(loader); definitionsHolder.set(definitions); } } } return definitions.stream().map(def -> def.getServiceClass()).collect(Collectors.toList()); }

2.4 加载文件,对实例排序 

//加载文件路径private static final String SERVICES_DIRECTORY = "META-INF/services/";private static final String SEATA_DIRECTORY = "META-INF/seata/";
private List<ExtensionDefinition> findAllExtensionDefinition(ClassLoader loader) { List<ExtensionDefinition> extensionDefinitions = new ArrayList<>(); try { loadFile(SERVICES_DIRECTORY, loader, extensionDefinitions); loadFile(SEATA_DIRECTORY, loader, extensionDefinitions); } catch (IOException e) { throw new EnhancedServiceNotFoundException(e); }
//After loaded all the extensions,sort the caches by order if (!nameToDefinitionsMap.isEmpty()) { for (List<ExtensionDefinition> definitions : nameToDefinitionsMap.values()) { Collections.sort(definitions, (def1, def2) -> { int o1 = def1.getOrder(); int o2 = def2.getOrder(); return Integer.compare(o1, o2); }); } }
if (!extensionDefinitions.isEmpty()) { Collections.sort(extensionDefinitions, (definition1, definition2) -> { int o1 = definition1.getOrder(); int o2 = definition2.getOrder(); return Integer.compare(o1, o2); }); } //返回排序后的扩展类集合 return extensionDefinitions; }

2.5 总结下Java类加载

ExtClassLoader AppClassLoader 均继承URLClassLoader

  • AppClassLoader 应用类加载器,又称为系统类加载器
  • ExtClassLoader 扩展类加载器 默认加载JAVA_HOME/jre/lib/ext/目录下的所有jar包;ExtClassLoader初始化过程中,将父类加载器设置成了null, 因为 BootstrapClassLoader是 C++编写,对于 Java 本身来说它是不存在的。所以此处设置null表示它的父类加载器就是启动类加载器
  • BootstrapClassLoader 启动类加载器 顶层的类加载器 JDK中的核心ClassLoader类库,如:rt.jar、resources.jar、charsets.jar等

下图loadFile方法中 loader.getResources(fileName),ClassLoader.getSystemResources(fileName) 区别 :

  • getSystemResources先获取系统类加载器,获取不到则启动类加载器查资源, 最后调用system.getResources(name)

class.getResource和classloader.getResource区别:

  • class的getResource不加“/”,会从class这个类所在的路径开始往下搜索资源,如果加上“/”,会从工程的根目录,也就是截图里的target/classes这个路径下开始搜索资源
  • classloader的getResource不加“/”,会通过双亲委派向上加载,未加载到,则通过当前类加载器加载classpath根目录资源;如果加上“/”,表示Boot ClassLoader中的加载范围,因为这个类加载器是C++实现的,所以加载范围为null
public Enumeration<URL> getResources(String name) throws IOException { @SuppressWarnings("unchecked") Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2]; if (parent != null) { tmp[0] = parent.getResources(name); } else { tmp[0] = getBootstrapResources(name); } tmp[1] = findResources(name);
return new CompoundEnumeration<>(tmp); }

public static Enumeration<URL> getSystemResources(String name) throws IOException{ ClassLoader system = getSystemClassLoader(); if (system == null) { return getBootstrapResources(name); } return system.getResources(name);}

当前类加载器加载文件路径, 实例化后写入集合

//查找目录下文件private void loadFile(String dir, ClassLoader loader, List<ExtensionDefinition> extensions) throws IOException { String fileName = dir + type.getName(); Enumeration<java.net.URL> urls; if (loader != null) { //此类所在的包下取资源 urls = loader.getResources(fileName); } else { urls = ClassLoader.getSystemResources(fileName); } if (urls != null) { while (urls.hasMoreElements()) { java.net.URL url = urls.nextElement(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), Constants.DEFAULT_CHARSET))) { String line; while ((line = reader.readLine()) != null) { final int ci = line.indexOf('#'); if (ci >= 0) { line = line.substring(0, ci); } line = line.trim(); if (line.length() > 0) { try { ExtensionDefinition extensionDefinition = getUnloadedExtensionDefinition(line, loader); if (extensionDefinition == null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("The same extension {} has already been loaded, skipped", line); } continue; } extensions.add(extensionDefinition); } catch (LinkageError | ClassNotFoundException e) { LOGGER.warn("Load [{}] class fail. {}", line, e.getMessage()); } } } } catch (Throwable e) { LOGGER.warn("load clazz instance error: {}", e.getMessage()); } } } }

2.6 反射加载class 

private ExtensionDefinition getUnloadedExtensionDefinition(String className, ClassLoader loader) throws ClassNotFoundException { //Check whether the definition has been loaded if (!isDefinitionContainsClazz(className, loader)) { //实例化class Class<?> clazz = Class.forName(className, true, loader); String serviceName = null; Integer priority = 0; Scope scope = Scope.SINGLETON; LoadLevel loadLevel = clazz.getAnnotation(LoadLevel.class); if (loadLevel != null) { //获取注解定义参数,order为排序值,scope默认单例 serviceName = loadLevel.name(); priority = loadLevel.order(); scope = loadLevel.scope(); } ExtensionDefinition result = new ExtensionDefinition(serviceName, priority, scope, clazz); classToDefinitionMap.put(clazz, result); if (serviceName != null) { CollectionUtils.computeIfAbsent(nameToDefinitionsMap, serviceName, e -> new ArrayList<>()) .add(result); } return result; } return null; }

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/221962.html

联系我们
联系我们
分享本页
返回顶部