04.Dubbo 源码解析之 ExtensionLoader

1. 环境搭建

  • 代码已经上传至 https://github.com/masteryourself/dubbo ,分支名称是 masteryourself-2.7.3-release

  • provider 是 dubbo-demo-xml-provider 工程,启动类是 Application

  • consumer 是 dubbo-demo-xml-consumer 工程,启动类是 Application

2. 源码解析

2.1 流程预览

2.1.1 关于 getExtensionLoader() 方法

image

2.1.2 关于 getExtension() 方法

image

2.1.3 整体流程预览
// 1. 从 【ServiceConfig】 的静态变量开始
private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension() ->
	// 获取 【Protocol】 的 ExtensionLoader
	org.apache.dubbo.common.extension.ExtensionLoader#getExtensionLoader ->
		// 初始化 【ExtensionLoader】,调用 ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension() 方法
		org.apache.dubbo.common.extension.ExtensionLoader#<init> ->
			// 获取 【ExtensionFactory】 的动态代理实现
			org.apache.dubbo.common.extension.ExtensionLoader#getAdaptiveExtension

				// 1.1 获取 【ExtensionFactory】 的动态代理类,调用 newInstance() 方法初始化实例
				org.apache.dubbo.common.extension.ExtensionLoader#createAdaptiveExtension
				
					// 1.1.1 获取 【ExtensionFactory】 的动态代理类
					org.apache.dubbo.common.extension.ExtensionLoader#getAdaptiveExtensionClass

						// 1.1.1.1 初始化 【ExtensionFactory】 接口对应的所有 Extension
						org.apache.dubbo.common.extension.ExtensionLoader#getExtensionClasses ->
							
							// 1.1.1.1.1(*) 解析 Dubbo 的 spi,查找 【META-INF/dubbo/internal/】、【META-INF/dubbo/】、【META-INF/services/】 三个目录下的接口文件
							org.apache.dubbo.common.extension.ExtensionLoader#loadExtensionClasses

								// 1.1.1.1.1.1 解析类上的 @SPI 注解,把 value 取出,缓存在 cachedDefaultName 属性中
								org.apache.dubbo.common.extension.ExtensionLoader#cacheDefaultExtensionName

								// 1.1.1.1.1.2 拼装接口文件路径,解析文件内容
								org.apache.dubbo.common.extension.ExtensionLoader#loadDirectory ->
									// 循环解析每一行内容
									org.apache.dubbo.common.extension.ExtensionLoader#loadResource

										// 1.1.1.1.1.2.1(*) 解析具体类
										org.apache.dubbo.common.extension.ExtensionLoader#loadClass

											// 1.1.1.1.1.2.1.1 如果类上有 @Adaptive 注解,则把这个类作为动态代理类赋值给 【cachedAdaptiveClass】
											org.apache.dubbo.common.extension.ExtensionLoader#cacheAdaptiveClass

											// 1.1.1.1.1.2.1.2 如果是 wrapper 类(判断依据是:是否有以这个接口为参数的构造方法),存储到 【cachedWrapperClasses】 set 集合中,因此是无序的
											org.apache.dubbo.common.extension.ExtensionLoader#cacheWrapperClass

											// 1.1.1.1.1.2.1.3 如果不是上述两种,则存储到 【cachedActivates】 map 集合中
											org.apache.dubbo.common.extension.ExtensionLoader#cacheActivateClass

						// 1.1.1.2 如果所有实现类都没有 @Adaptive 注解,那么就会动态创建代理类,然后赋值给 【cachedAdaptiveClass】
						// 代理类类名规则为:接口名+$Adaptive,如 【ProxyFactory$Adaptive】
						org.apache.dubbo.common.extension.ExtensionLoader#createAdaptiveExtensionClass

							// 1.1.1.2.1 为接口生成动态代理代码
							org.apache.dubbo.common.extension.AdaptiveClassCodeGenerator#generate

							// 1.1.1.2.2 把生成的代码编译后,用 classLoader 加载
							org.apache.dubbo.common.compiler.Compiler#compile

					// 1.1.2 调用 newInstance() 方法初始化 【AdaptiveExtensionFactory】
					// 在构造方法里,会获取 ExtensionFactory 的所有 Extension 赋值给 factories 属性,这里有 【SpiExtensionFactory】 和 【SpringExtensionFactory】 两个
					org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory#<init>

						// 1.1.2.1 获取 name 对应的 Extension,分别为 【spi】 和 【spring】
						org.apache.dubbo.common.extension.ExtensionLoader#getExtension ->

							// 1.1.2.1.1(*) 创建 Extension,这里会循环用 wrapper 类包装
							org.apache.dubbo.common.extension.ExtensionLoader#createExtension

								// 1.1.2.1.1.1(*) 对 set 开头的方法进行自动注入,wrapper 类也会调用此方法进行自动注入
								org.apache.dubbo.common.extension.ExtensionLoader#injectExtension

									// 1.1.2.1.1.1.1(*) 先后从 【SpiExtensionFactory】、【SpringExtensionFactory】 中获取对应的值
									org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory#getExtension

										// 1.1.2.1.1.1.1.1(*) 获取接口对应的 ExtensionLoader,返回动态代理实现
										org.apache.dubbo.common.extension.factory.SpiExtensionFactory#getExtension

										// 1.1.2.1.1.1.1.2(*) 在 Spring 中:先根据名称获取,找不到再根据类型获取
										org.apache.dubbo.config.spring.extension.SpringExtensionFactory#getExtension

					// 1.1.3 调用 injectExtension() 方法完成自动注入
					org.apache.dubbo.common.extension.ExtensionLoader#injectExtension

2.2 流程详解

2.2.1 ExtensionLoader#loadExtensionClasses(1.1.1.1.1)
  • org.apache.dubbo.common.extension.ExtensionLoader
private Map<String, Class<?>> loadExtensionClasses() {

    // 解析类上的 @SPI 注解,把 value 取出,缓存在 cachedDefaultName 属性中
    cacheDefaultExtensionName();

    Map<String, Class<?>> extensionClasses = new HashMap<>();

    // 读取 META-INF/dubbo/internal/ 路径
    loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
    loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));

    // 读取 META-INF/dubbo/ 路径
    loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
    loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));

    // 读取 META-INF/services/ 路径
    loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
    loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
    return extensionClasses;
}
2.2.2 ExtensionLoader#loadClass(1.1.1.1.1.2.1)
  • org.apache.dubbo.common.extension.ExtensionLoader
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
    // 判断是不是接口的实现类,不是就直接报错
        if (!type.isAssignableFrom(clazz)) {
        throw new IllegalStateException("Error occurred when loading extension class (interface: " +
                type + ", class line: " + clazz.getName() + "), class "
                + clazz.getName() + " is not subtype of interface.");
    }
    
    // 如果类上有 @Adaptive 注解,则赋值给 【cachedAdaptiveClass】
    if (clazz.isAnnotationPresent(Adaptive.class)) {
        cacheAdaptiveClass(clazz);
    
    // 如果是 wrapper 类(判断依据是:是否有以这个接口为参数的构造方法),存储到 【cachedWrapperClasses】 set 集合中,因此 wrapper 是无序的
    } else if (isWrapperClass(clazz)) {
        cacheWrapperClass(clazz);
    } else {
        
        // 如果不是上述两种
        clazz.getConstructor();
        if (StringUtils.isEmpty(name)) {
            name = findAnnotationName(clazz);
            if (name.length() == 0) {
                throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
            }
        }

        String[] names = NAME_SEPARATOR.split(name);
        if (ArrayUtils.isNotEmpty(names)) {
        
            // 存储到 【cachedActivates】 map 集合中
            cacheActivateClass(clazz, names[0]);
            for (String n : names) {
                cacheName(clazz, n);
                saveInExtensionClass(extensionClasses, clazz, name);
            }
        }
    }
}
2.2.3 ExtensionLoader#createExtension(1.1.2.1.1)
  • org.apache.dubbo.common.extension.ExtensionLoader
private T createExtension(String name) {
    
    ...
    
    try {
        
        ...
        
        // 自动注入,对 set 开头的方法进行自动注入
        injectExtension(instance);
        Set<Class<?>> wrapperClasses = cachedWrapperClasses;
        
        // 获取所有的 wrapper 类
        if (CollectionUtils.isNotEmpty(wrapperClasses)) {
            for (Class<?> wrapperClass : wrapperClasses) {
                // 循环使用 wrapper 类包装,wrapper 类也会调用 injectExtension() 方法完成自动注入
                instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
            }
        }
        
        // 返回循环包装后的实例
        return instance;
    } catch (Throwable t) {
        throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
                type + ") couldn't be instantiated: " + t.getMessage(), t);
    }
}
2.2.4 ExtensionLoader#injectExtension(1.1.2.1.1.1)
  • org.apache.dubbo.common.extension.ExtensionLoader
private T injectExtension(T instance) {
    try {
        if (objectFactory != null) {
            for (Method method : instance.getClass().getMethods()) {
                if (isSetter(method)) {
                    /**
                     * Check {@link DisableInject} to see if we need auto injection for this property
                     */
                    if (method.getAnnotation(DisableInject.class) != null) {
                        continue;
                    }
                    Class<?> pt = method.getParameterTypes()[0];
                    if (ReflectUtils.isPrimitives(pt)) {
                        continue;
                    }
                    try {
                        String property = getSetterProperty(method);
                        Object object = objectFactory.getExtension(pt, property);
                        if (object != null) {
                            method.invoke(instance, object);
                        }
                    } catch (Exception e) {
                        logger.error("Failed to inject via method " + method.getName()
                                + " of interface " + type.getName() + ": " + e.getMessage(), e);
                    }
                }
            }
        }
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
    return instance;
}
2.2.5 AdaptiveExtensionFactory#getExtension(1.1.2.1.1.1.1)
  • org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
public <T> T getExtension(Class<T> type, String name) {
    // 先后从【SpiExtensionFactory】、【SpringExtensionFactory】 中获取对应的值
    for (ExtensionFactory factory : factories) {
        T extension = factory.getExtension(type, name);

        // 如果找到值就直接返回
        if (extension != null) {
            return extension;
        }
    }
    return null;
}
2.2.6 SpiExtensionFactory#getExtension(1.1.2.1.1.1.1.1)
  • org.apache.dubbo.common.extension.factory.SpiExtensionFactory
public <T> T getExtension(Class<T> type, String name) {

    // 如果自动注入的值是接口且有 @SPI 注解
    if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {

        // 获取接口对应的 ExtensionLoader
        ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
        if (!loader.getSupportedExtensions().isEmpty()) {

            // 返回动态代理实现
            return loader.getAdaptiveExtension();
        }
    }
    return null;
}
2.2.7 SpringExtensionFactory#getExtension(1.1.2.1.1.1.1.2)
  • org.apache.dubbo.config.spring.extension.SpringExtensionFactory
public <T> T getExtension(Class<T> type, String name) {

    //SPI should be get from SpiExtensionFactory
    // 如果自动注入的值是接口且有 @SPI 注解,则直接返回
    if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
        return null;
    }

    // 先根据名称获取
    for (ApplicationContext context : CONTEXTS) {
        if (context.containsBean(name)) {
            Object bean = context.getBean(name);
            if (type.isInstance(bean)) {
                return (T) bean;
            }
        }
    }

    ...

    // 再根据类型获取
    for (ApplicationContext context : CONTEXTS) {
        try {
            return context.getBean(type);
        } catch (NoUniqueBeanDefinitionException multiBeanExe) {
            logger.warn("Find more than 1 spring extensions (beans) of type " + type.getName() + ", will stop auto injection. Please make sure you have specified the concrete parameter type and there's only one extension of that type.");
        } catch (NoSuchBeanDefinitionException noBeanExe) {
            if (logger.isDebugEnabled()) {
                logger.debug("Error when get spring extension(bean) for type:" + type.getName(), noBeanExe);
            }
        }
    }

    ...
    
}
发布了37 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/masteryourself/article/details/103759030