Seata源码学习笔记(一):重写 SPI

一、common下的loader

1、SPI (EnhancedServiceLoader)

1)、测试

@Test
public void testLoadByClassAndClassLoader() {
    
    
	// 实际就是通过反射,创建对象
    Hello load = EnhancedServiceLoader.load(Hello.class, Hello.class.getClassLoader());
    Assertions.assertEquals(load.say(), "Olá.");
}

2)、主流程

private static class InnerEnhancedServiceLoader<S> {
    
    
	private static final Logger LOGGER = LoggerFactory.getLogger(InnerEnhancedServiceLoader.class);
	private static final String SERVICES_DIRECTORY = "META-INF/services/";
	private static final String SEATA_DIRECTORY = "META-INF/seata/";
	
	// 下面的a流程会挨个给这些对象添加值
	private static final ConcurrentMap<Class<?>, InnerEnhancedServiceLoader<?>> SERVICE_LOADERS =
	        new ConcurrentHashMap<>();
	
	private final Class<S> type;
	private final Holder<List<ExtensionDefinition>> definitionsHolder = new Holder<>();
	private final ConcurrentMap<ExtensionDefinition, Holder<Object>> definitionToInstanceMap =
	        new ConcurrentHashMap<>();
	private final ConcurrentMap<String, List<ExtensionDefinition>> nameToDefinitionsMap = new ConcurrentHashMap<>();
	private final ConcurrentMap<Class<?>, ExtensionDefinition> classToDefinitionMap = new ConcurrentHashMap<>();
	
	private InnerEnhancedServiceLoader(Class<S> type) {
    
    
	    this.type = type;
	}
	
	/**
	 * Get the ServiceLoader for the specified Class
	 *
	 * @param type the type of the extension point
	 * @param <S>  the type
	 * @return the service loader
	 */
	private static <S> InnerEnhancedServiceLoader<S> getServiceLoader(Class<S> type) {
    
    
	    if (type == null) {
    
    
	        throw new IllegalArgumentException("Enhanced Service type == null");
	    }
	    // 添加<Hello.class, new InnerEnhancedServiceLoader<>(Hello.class)> 到 SERVICE_LOADERS
	    // computeIfAbsent 方法似乎只是将 map 的 computeIfAbsent 方法变成了静态的,并调换了下判断顺序
	    return (InnerEnhancedServiceLoader<S>)CollectionUtils.computeIfAbsent(SERVICE_LOADERS, type,
	        key -> new InnerEnhancedServiceLoader<>(type));
	}
	
	/**
     * Specify classLoader to load the service provider
     *
     * @param loader the loader
     * @return s s
     * @throws EnhancedServiceNotFoundException the enhanced service not found exception
     */
     // 很多种load,这里只看这一种,其他可以类比这个
    private S load(ClassLoader loader) throws EnhancedServiceNotFoundException {
    
    
        return loadExtension(loader, null, null);
    }

	// 也有几种,这里只看这一种,其他可以类比这个
	@SuppressWarnings("rawtypes")
	private S loadExtension(ClassLoader loader, Class[] argTypes,
	                        Object[] args) {
    
    
	    try {
    
    
	    	// a、初始化上面的那些对象,第一次 debug,结果如下
	        loadAllExtensionClass(loader);
	        // b、获取 definitionsHolder 中的 ExtensionDefinition 集合中的最后一个
	        ExtensionDefinition defaultExtensionDefinition = getDefaultExtensionDefinition();
	        // c、通过反射实例化上步得到的 defaultExtensionDefinition 里的 serviceClass
	        // 第二次 debug,结果如下
	        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));
	        }
	    }
	}
}

3)、分解主流程

a、初始化数据

private final Holder<List<ExtensionDefinition>> definitionsHolder = new Holder<>();

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());
}

/**
 * Helper Class for hold a value.
 * @param <T>
 */
private static class Holder<T> {
    
    
    private volatile T value;

    private void set(T value) {
    
    
        this.value = value;
    }

    private T get() {
    
    
        return value;
    }
}
private static final String SERVICES_DIRECTORY = "META-INF/services/";
private static final String SEATA_DIRECTORY = "META-INF/seata/";

@SuppressWarnings("rawtypes")
private List<ExtensionDefinition> findAllExtensionDefinition(ClassLoader loader) {
    
    
    List<ExtensionDefinition> extensionDefinitions = new ArrayList<>();
    try {
    
    
    	// 看第一个loadFile,下面的可以类比
        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;
}
@SuppressWarnings("rawtypes")
private void loadFile(String dir, ClassLoader loader, List<ExtensionDefinition> extensions)
        throws IOException {
    
    
    // fileName = META-INF/services/io.seata.common.loader.Hello
    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 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());
            }
        }
    }
}
private final ConcurrentMap<String, List<ExtensionDefinition>> nameToDefinitionsMap = new ConcurrentHashMap<>();
private final ConcurrentMap<Class<?>, ExtensionDefinition> classToDefinitionMap = new ConcurrentHashMap<>();

private ExtensionDefinition getUnloadedExtensionDefinition(String className, ClassLoader loader)
    throws ClassNotFoundException {
    
    
    //Check whether the definition has been loaded
    if (!isDefinitionContainsClazz(className, loader)) {
    
    
        Class<?> clazz = Class.forName(className, true, loader);
        String serviceName = null;
        Integer priority = 0;
        Scope scope = Scope.SINGLETON;
        // 读 Hello 上的 LoadLevel 注解
        LoadLevel loadLevel = clazz.getAnnotation(LoadLevel.class);
        if (loadLevel != null) {
    
    
            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;
}

b、

private ExtensionDefinition getDefaultExtensionDefinition() {
    
    
    List<ExtensionDefinition> currentDefinitions = definitionsHolder.get();
    return CollectionUtils.getLast(currentDefinitions);
}

c、通过反射实例化

private S getExtensionInstance(ExtensionDefinition definition, ClassLoader loader, Class[] argTypes,
                               Object[] args) {
    
    
    if (definition == null) {
    
    
        throw new EnhancedServiceNotFoundException("not found service provider for : " + type.getName());
    }
    // LoadLevel 注解的 scope 字段,是否为单例
    if (Scope.SINGLETON.equals(definition.getScope())) {
    
    
        Holder<Object> holder = CollectionUtils.computeIfAbsent(definitionToInstanceMap, definition,
            key -> new Holder<>());
        Object instance = holder.get();
        if (instance == null) {
    
    
            synchronized (holder) {
    
    
                instance = holder.get();
                if (instance == null) {
    
    
                    instance = createNewExtension(definition, loader, argTypes, args);
                    holder.set(instance);
                }
            }
        }
        return (S)instance;
    } else {
    
    
        return createNewExtension(definition, loader, argTypes, args);
    }
}

4)、debug

在这里插入图片描述
在这里插入图片描述

二、影响

比如注册中心,有 nacos、zk 等代码,只需配置下类似下面的文件,就可以加载对应的代码。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_36514197/article/details/119778218
今日推荐