Dubbo-SPI(三)-getExtension实现原理

Dubbo-SPI系列文章目录

Dubbo-SPI(一)-加载机制概述
Dubbo-SPI(二)-@SPI注解
Dubbo-SPI(三)-getExtension实现原理
Dubbo-SPI(四)-@Adaptive注解
Dubbo-SPI(五)-@Activate注解



ExtensionLoader工作原理

ExtensionLoader 类似 JDK标准SPI里的ServiceLoader类
代码ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension() 的作用是 获取 Protocol接口 的 适配器类

工作流程

ExtensionLoader的逻辑入口可以分为三个

  • getExtension 获取普通扩展类
  • getAdaptiveExtension 获取自动适应扩展类
  • getActivateExtension 获取自动激活扩展类

在这里插入图片描述

三个入口中,getActivateExtension 对 getExtension 的依赖比较重,getAdaptiveExtension 则相对独立
getExtension 是 整个扩展器中 最核心的方法,实现了 一个完成的 普通扩展类的加载过程。
加载过程的每一步,都会先检查缓存中 是否已存在所需要的数据,如果存在则直接从缓存读取,没有则重新加载
这个方法(getExtension) 每次只会 根据名称 返回一个 扩展点实现类

getExtension 初始化过程可以分为四步:

  1. 框架 读取 SPI(扩展点)对应下的路径配置文件,并根据配置 加载 所有 扩展类缓存(不初始化)
  2. 根据 传入的名称 初始化 对应扩展类
  3. 尝试查找 符合条件的包装类:包含扩展点的setter方法;包含扩展点类型相同的构造函数,为其注入扩展类实例
  4. 返回对应的扩展类实例

getAdaptiveExtension 只有加载配置信息部分 和 getExtension 共用一个方法,同样的,也会先检查缓存中是否存在 已经初始化好的Adaptive实例,没有 则 调用createAdaptiveExtension重新初始化
getAdaptiveExtension 初始化过程分为四步:

  1. 和getExtension 一样先加载配置文件
  2. 生成 自适应扩展类的代码字符串
  3. 获取 类加载器 和 编译器,并编译2生成的代码字符串
  4. 返回对应的 自适应扩展类实例

getExtension实现原理

入口

// 入参name是指定的扩展名
public T getExtension(String name) {
	// 第二个参数:wrap-是否包装
	return getExtension(name, true);
}

public T getExtension(String name, boolean wrap) {
	if (StringUtils.isEmpty(name)) {
		throw new IllegalArgumentException("Extension name == null");
	}
	// 如果name=true,返回 默认扩展类 的 实例
	// 这里可能返回null
	if ("true".equals(name)) {
		return getDefaultExtension();
	}
	// 根据 扩展名 创建持有(扩展类)实例的 Holder对象
	final Holder<Object> holder = getOrCreateHolder(name);
	Object instance = holder.get();
	if (instance == null) {
		synchronized (holder) {
			instance = holder.get();
			if (instance == null) {
				// 创建 扩展实例
				instance = createExtension(name, wrap);
				holder.set(instance);
			}
		}
	}
	// 返回扩展实例
	return (T) instance;
}

1.getDefaultExtension-获取默认扩展的实例

// 缓存 默认扩展名
private String cachedDefaultName;

public T getDefaultExtension() {
	// 获取 扩展类
	getExtensionClasses();
	// 如果 默认的扩展名 为空 或 =true,返回null
	if (StringUtils.isBlank(cachedDefaultName) || "true".equals(cachedDefaultName)) {
		return null;
	}
	// 根据 默认的扩展名 获取 扩展实例
	return getExtension(cachedDefaultName);
}

2.getExtensionClasses-获取扩展类

// 普通扩展类(的)缓存,其实是一个map
// 缓存的是Class类型的对象
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();

private Map<String, Class<?>> getExtensionClasses() {
	// 从cachedClasses中获取缓存集合,如果没有,对cachedClasses加同步锁后再获取,如果还没有,走loadExtensionClasses获取扩展类,放入cachedClasses
	Map<String, Class<?>> classes = cachedClasses.get();
	if (classes == null) {
		synchronized (cachedClasses) {
			classes = cachedClasses.get();
			if (classes == null) {
				// 加载扩展类
				classes = loadExtensionClasses();
				// 设置 普通扩展类 缓存
				cachedClasses.set(classes);
			}
		}
	}
	return classes;
}

3.loadExtensionClasses-加载扩展类

/**
 * synchronized in getExtensionClasses
 * 同步方法
 */
private Map<String, Class<?>> loadExtensionClasses() {
	// 缓存 默认的扩展名
	cacheDefaultExtensionName();

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

	// 循环 所有策略加载的实现类,放到extensionClasses这个map中
	for (LoadingStrategy strategy : strategies) {
		loadDirectory(extensionClasses,
			// 目录
			strategy.directory(),
			// 扩展接口全路径类名
			type.getName(),
			// 是否优先通过extensionLoaderClass加载
			strategy.preferExtensionClassLoader(),
			// 目录是否可以被覆盖
			strategy.overridden(),
			// 目录排除包
			strategy.excludedPackages());
		loadDirectory(extensionClasses,
			strategy.directory(),
			type.getName().replace("org.apache", "com.alibaba"),
			strategy.preferExtensionClassLoader(),
			strategy.overridden(),
			strategy.excludedPackages());
	}

	return extensionClasses;
}

4.cacheDefaultExtensionName-缓存默认扩展名

// 默认扩展名缓存
private String cachedDefaultName;

private void cacheDefaultExtensionName() {
	// 检测当前扩展接口是否使用了SPI注解,如果没有SPI注解返回NULL
	final SPI defaultAnnotation = type.getAnnotation(SPI.class);
	if (defaultAnnotation == null) {
		return;
	}

	// 获取SPI注解的value值!!!
	// 去掉空格,用,来分割,如果>1个,则抛出异常
	String value = defaultAnnotation.value();
	if ((value = value.trim()).length() > 0) {
		String[] names = NAME_SEPARATOR.split(value);
		if (names.length > 1) {
			throw new IllegalStateException("More than 1 default extension name on extension " + type.getName()
                        + ": " + Arrays.toString(names));
		}
		// 用SPI注解的value值 设置为 当前扩展接口(type) 的 默认的扩展名 到 cachedDefaultName缓存中
		if (names.length == 1) {
			cachedDefaultName = names[0];
		}
	}
}

5.type的设置

type是在ExtensionLoader的构造方法中被设置的
而 ExtensionLoader的构造方法 会在 getExtensionLoader方法中被调用

private final Class<?> type;

// 这是一个私有方法,只能被getExtensionLoader方法调用
// 所以针对每一个扩展类,只会有一个ExtensionLoader
private ExtensionLoader(Class<?> type) {
	// 使用@SPI注解的扩展接口
	this.type = type;
	// 如果扩展接口  是ExtensionFactory类型,那么objectFactory设置为null
	// 如果扩展接口不是ExtensionFactory类型,获取一个ExtensionFactory接口的自适应扩展实例,赋值给objectFactory
	// 每个Extension只能有一个@Adaptive自适应类型的实现,如果没有,dubbo会动态生成一个类
	objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}

// getExtensionLoader方法
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
	// ...
	
	// 判断扩展接口是否使用了SPI注解
	if (!withExtensionAnnotation(type)) {
		throw new IllegalArgumentException("Extension type (" + type +
                    ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
	}

	// 先从EXTENSION_LOADERS缓存中获取,如果没有,new一个构造参数=type的ExtensionLoader,然后放入缓存,再获取并返回
	ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
	if (loader == null) {
		EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
		loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
	}
	return loader;
}

// 扩展类 与 该扩展类对应的ExtensionLoader 缓存
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64);

private static <T> boolean withExtensionAnnotation(Class<T> type) {
	// 判断当前扩展接口是否使用了SPI注解
	return type.isAnnotationPresent(SPI.class);
}

6.loadExtensionClasses中的strategies

loadExtensionClasses中的loadDirectory是基于loadLoadingStrategies方法设置的strategies数据进行循环的

private static volatile LoadingStrategy[] strategies = loadLoadingStrategies();

/**
 * Load all {@link Prioritized prioritized} {@link LoadingStrategy Loading Strategies} via {@link ServiceLoader}
 * 加载所有的策略配置的实现类,进行排序,返回一个新数组
 * LoadingStrategy接口有4个实现
 * DubboLoadingStrategy-META-INF/dubbo/
 * DubboInternalLoadingStrategy-META-INF/dubbo/internal/
 * DubboExternalLoadingStrategy-META-INF/dubbo/external/
 * ServicesLoadingStrategy-META-INF/services/
 * 
 * DubboInternalLoadingStrategy不循允许覆盖,其他都允许覆盖
 * @return non-null
 * @since 2.7.7
 */
private static LoadingStrategy[] loadLoadingStrategies() {
	// load方法通过ServiceLoader.load加载了LoadingStrategy接口的所有实现类
	// LoadingStrategy接口继承了Prioritized接口
	// Prioritized接口继承了Comparable泛型接口,其中compareTo方法的实现是使用getPriority的返回值进行比对
	// 所以LoadingStrategy排序是根据getPriority方法的返回值进行处理的
	return stream(load(LoadingStrategy.class).spliterator(), false)
		.sorted()
		.toArray(LoadingStrategy[]::new);
}

7.loadDirectory-加载配置文件目录

回到loadExtensionClasses,继续看loadDirectory

/**
  *
  * @param extensionClasses 最后要保存的集合
  * @param dir 配置文件路径
  * @param type 扩展接口全路径类名
  * @param extensionLoaderClassLoaderFirst 是否优先通过extensionLoaderClass加载
  * @param overridden 是否覆盖
  * @param excludedPackages 排除包
  */
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
	boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) {
	// 获取文件在项目中的路径
	// META-INF/dubbo/扩展接口全路径类名
	String fileName = dir + type;
	try {
		Enumeration<java.net.URL> urls = null;
		// 获取ExtensionLoader的类加载器
		ClassLoader classLoader = findClassLoader();

		// try to load from ExtensionLoader's ClassLoader first
		// 尝试优先通过ExtensionLoader的类加载器 进行加载资源文件
		// 目前extensionLoaderClassLoaderFirst都是false
		if (extensionLoaderClassLoaderFirst) {
			// 先获取ExtensionLoader的类加载器
			ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
			// 如果 系统加载器 != ExtensionLoader的类加载器,则用ExtensionLoader的类加载器 获取资源文件
			if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
				urls = extensionLoaderClassLoader.getResources(fileName);
			}
		}

		// 加载当前fileName文件
		// TODO getResources 和 getSystemResources的区别?
		if (urls == null || !urls.hasMoreElements()) {
			if (classLoader != null) {
				urls = classLoader.getResources(fileName);
			} else {
				urls = ClassLoader.getSystemResources(fileName);
			}
		}

		if (urls != null) {
			// 迭代 加载同名文件的内容
			while (urls.hasMoreElements()) {
				java.net.URL resourceURL = urls.nextElement();
				loadResource(extensionClasses, classLoader, resourceURL, overridden, excludedPackages);
			}
		}
	} catch (Throwable t) {
		logger.error("Exception occurred when loading extension class (interface: " +
                    type + ", description file: " + fileName + ").", t);
	}
}

private static ClassLoader findClassLoader() {
	// 获取ExtensionLoader的类加载器
	return ClassUtils.getClassLoader(ExtensionLoader.class);
}

8.loadResource-加载资源

/**
  * 
  * @param extensionClasses 最后要保存的集合
  * @param classLoader 类加载器
  * @param resourceURL 资源路径
  * @param overridden 是否覆盖
  * @param excludedPackages 排除包
  */
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
	java.net.URL resourceURL, boolean overridden, String... excludedPackages) {
	try {
		// 从resourceURL中进行读取
		try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
			String line;
			String clazz = null;
			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 {
						String name = null;
						int i = line.indexOf('=');
						if (i > 0) {
							// =之前的作为扩展实现名
							name = line.substring(0, i).trim();
							// =之后的是扩展类的具体实现的全路径类名
							clazz = line.substring(i + 1).trim();
						} else {
							// 没有=直接使用一整行作为扩展类的具体实现的全路径类名
							clazz = line;
						}
						// 如果扩展类实现的全路径类名不为空 且 不在被排除的范围内,则进行加载类
						// 先根据clazz字符串,使用classLoader 生成一个Class类型对象 
						// 然后再进行loadClass
						if (StringUtils.isNotEmpty(clazz) && !isExcluded(clazz, excludedPackages)) {
							loadClass(extensionClasses, resourceURL, Class.forName(clazz, true, classLoader), name, overridden);
						}
					} catch (Throwable t) {
						IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
						// 加入异常集合
						exceptions.put(line, e);
					}
				}
			}
		}
	} catch (Throwable t) {
		logger.error("Exception occurred when loading extension class (interface: " +
			type + ", class file: " + resourceURL + ") in " + resourceURL, t);
	}
}

9.loadClass-加载扩展类

/**
  *
  * @param extensionClasses 集合
  * @param resourceURL 资源文件路径
  * @param clazz 配置文件中扩展类实现的Class类型对象
  * @param name 配置文件中的扩展实现名
  * @param overridden 是否覆盖
  * @throws NoSuchMethodException NoSuchMethodException
  */
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name,
						boolean overridden) throws NoSuchMethodException {
        // 判断扩展接口type是否是扩展类实现clazz的父类
        // 也就是说判断扩展类实现clazz是否实现了扩展接口type
	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
	if (clazz.isAnnotationPresent(Adaptive.class)) {
		// 缓存 自适应扩展类 到 cachedAdaptiveClass
		cacheAdaptiveClass(clazz, overridden);
	} else if (isWrapperClass(clazz)) { // 判断扩展类实现上是否是包装类
		// 缓存 包装扩展类 到 cachedWrapperClasses
		cacheWrapperClass(clazz);
	} else {
		// 尝试clazz是否有 无参构造方法
		clazz.getConstructor();
		if (StringUtils.isEmpty(name)) {
			// 如果扩展实现名(配置文件中=前面的)为空,则获取扩展类实现上的 @Extension 注解的value值
			// 如果@Extension的value也没有,则使用处理后的小写类名
			name = findAnnotationName(clazz);
			if (name.length() == 0) {
				throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
			}
		}

		// 用,对name进行分割
		// 这里要分割,是考虑到 自动激活的情况
		// 自动激活 也是 普通扩展来的一种,只是会根据不同条件同时激活罢了
		String[] names = NAME_SEPARATOR.split(name);
		if (ArrayUtils.isNotEmpty(names)) {
			// 缓存 扩展名 和 自动激活 到 cachedActivates
			cacheActivateClass(clazz, names[0]);
			for (String n : names) {
				// 缓存 扩展类、扩展名 到 cachedNames
				cacheName(clazz, n);
				// 保存 扩展名、扩展类 到 extensionClasses集合中
				saveInExtensionClass(extensionClasses, clazz, n, overridden);
			}
		}
	}
}

10.findAnnotationName-查询注解名称

先过针对自适应扩展 和 包装扩展的判断处理,看下findAnnotationName 及后续流程

private String findAnnotationName(Class<?> clazz) {
	// 尝试获取clazz上@Extension注解的value值
	org.apache.dubbo.common.Extension extension = clazz.getAnnotation(org.apache.dubbo.common.Extension.class);
	if (extension != null) {
		return extension.value();
	}

	// 如果clazz没有@Extension注解,获取clazz的简写名称
	String name = clazz.getSimpleName();
	// 如果 clazz的简写名称 是以 扩展接口type的简写名称 为结束的,则对clazz的简写名称 进行截取
	if (name.endsWith(type.getSimpleName())) {
		name = name.substring(0, name.length() - type.getSimpleName().length());
	}
	// 转换成小写返回
	return name.toLowerCase();
}

11.cacheActivateClass-处理自动激活扩展缓存

// 扩展名 与 自动激活 缓存
private final Map<String, Object> cachedActivates = new ConcurrentHashMap<>();

private void cacheActivateClass(Class<?> clazz, String name) {
	// 判断扩展类实现上是否有自动激活注解
	Activate activate = clazz.getAnnotation(Activate.class);
	if (activate != null) {
		// 缓存 扩展名 + 自动激活对象
		cachedActivates.put(name, activate);
	} else {
		// support com.alibaba.dubbo.common.extension.Activate
		com.alibaba.dubbo.common.extension.Activate oldActivate = clazz.getAnnotation(com.alibaba.dubbo.common.extension.Activate.class);
		if (oldActivate != null) {
			cachedActivates.put(name, oldActivate);
		}
	}
}

12.cacheName-处理扩展类与扩展名缓存

// 扩展类 与 扩展名 缓存
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();

private void cacheName(Class<?> clazz, String name) {
	if (!cachedNames.containsKey(clazz)) {
		cachedNames.put(clazz, name);
	}
}

13.saveInExtensionClass-保存扩展类到extensionClasses集合

private void saveInExtensionClass(Map<String, Class<?>> extensionClasses, Class<?> clazz, String name, boolean overridden) {
	// 先在extensionClasses集合中根据name获取一下
	Class<?> c = extensionClasses.get(name);
	// 如果extensionClasses集合中没有 或者 允许覆盖,则进行put
	if (c == null || overridden) {
		extensionClasses.put(name, clazz);
	} else if (c != clazz) {
		// 如果extensionClasses集合有 或者 不允许覆盖,则抛出异常
		String duplicateMsg = "Duplicate extension " + type.getName() + " name " + name + " on " + c.getName() + " and " + clazz.getName();
		logger.error(duplicateMsg);
		throw new IllegalStateException(duplicateMsg);
	}
}

14.cacheAdaptiveClass-处理自适应扩展缓存

回过头来看loadClass中的cacheAdaptiveClass

// 自适应扩展类 缓存,只能同时存在一个
private volatile Class<?> cachedAdaptiveClass = null;

private void cacheAdaptiveClass(Class<?> clazz, boolean overridden) {
        // 如果 自适应扩展类缓存cachedAdaptiveClass为空 或者 可以覆盖,则进行赋值
        if (cachedAdaptiveClass == null || overridden) {
            cachedAdaptiveClass = clazz;
        } else if (!cachedAdaptiveClass.equals(clazz)) {
            // 自适应扩展类缓存cachedAdaptiveClass 不等于 入参类clazz,则抛出异常
            throw new IllegalStateException("More than 1 adaptive class found: "
                    + cachedAdaptiveClass.getName()
                    + ", " + clazz.getName());
        }
    }

15.cacheWrapperClass-处理包装扩展

// 包装扩展类 缓存,不可重复,集合中不能有重复的包装扩展类
private Set<Class<?>> cachedWrapperClasses;

private void cacheWrapperClass(Class<?> clazz) {
	if (cachedWrapperClasses == null) {
		cachedWrapperClasses = new ConcurrentHashSet<>();
	}
	cachedWrapperClasses.add(clazz);
}

16.阶段小结

到此,上面是getExtensionClasses方法中loadExtensionClasses方法的处理逻辑,完成之后得到的Map<String, Class<?>>放入普通扩展类缓存cachedClasses中
以上处理,仅仅是把扩展类的Class对象 加载到jvm中,并没有做Class初始化。在加载Class文件时,会根据Class上的注释 来判断扩展点类型,再根据类型分类 做缓存。
接下来回到getExtension方法中继续往下

17.getOrCreateHolder-创建/获取Holder对象

// getExtension中有这么一行
final Holder<Object> holder = getOrCreateHolder(name);

// 扩展名 与 扩展对象 缓存
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();

// 入参name是getExtension中指定的扩展名
private Holder<Object> getOrCreateHolder(String name) {
	// 先从缓存中获取name对应的Holder,缓存中没有就new一个Holder
	// 注意此时Holder对象的Object是空
	Holder<Object> holder = cachedInstances.get(name);
	if (holder == null) {
		cachedInstances.putIfAbsent(name, new Holder<>());
		holder = cachedInstances.get(name);
	}
	return holder;
}

// 回到getExtension中继续
// 如果holder中没有扩展实例,则走createExtension
Object instance = holder.get();
if (instance == null) {
	synchronized (holder) {
		instance = holder.get();
		if (instance == null) {
			instance = createExtension(name, wrap);
			holder.set(instance);
		}
	}
}
return (T) instance;

18.createExtension-创建扩展实例

// 扩展类 与 扩展类初始化后的实例 缓存
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64);

private T createExtension(String name, boolean wrap) {
	// 通过getExtensionClasses获得普通扩展类缓存
	// 在缓存中查找指定name对应的普通扩展类缓存(类对象)
	Class<?> clazz = getExtensionClasses().get(name);
	if (clazz == null) {
		throw findException(name);
	}
	try {
		// 在缓存中查找 类对象 是否有对应的 类实例对象
		T instance = (T) EXTENSION_INSTANCES.get(clazz);
		// 如果不存在实例,就通过getDeclaredConstructor获取构造方法再newInstance,得到一个新实例,放到EXTENSION_INSTANCES缓存中
		if (instance == null) {
			EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance());
			instance = (T) EXTENSION_INSTANCES.get(clazz);
		}
		// 注入扩展类实例
		injectExtension(instance);

		// 如果wrap=true,要处理包装扩展类
		if (wrap) {

			List<Class<?>> wrapperClassesList = new ArrayList<>();
			// 如果 包装扩展类缓存不为空,则加入到wrapperClassesList列表中,并排序、反转
			if (cachedWrapperClasses != null) {
				wrapperClassesList.addAll(cachedWrapperClasses);
				wrapperClassesList.sort(WrapperComparator.COMPARATOR);
				Collections.reverse(wrapperClassesList);
			}

			// 循环wrapperClassesList列表,得到Wrapper注解
			if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
				for (Class<?> wrapperClass : wrapperClassesList) {
					Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
					// 如果包装类没有Wrapper注解 或 
					// 包装类的Wrapper注解的matches数组包含指定name 且 mismatches数组不包含指定name 
					if (wrapper == null
						|| (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {
						// 获取 包装类中参数类型为 扩展接口类型 的 构造方法,然后newInstance,把刚才实例化的扩展类传进去
						// 再injectExtension(注入扩展),得到具体实例
						instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
					}
				}
			}
		}

		// 最后 使用实例 初始化扩展
		initExtension(instance);
		return instance;
	} catch (Throwable t) {
		throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
			type + ") couldn't be instantiated: " + t.getMessage(), t);
	}
}

19.injectExtension-注入扩展实例

private final ExtensionFactory objectFactory;

private T injectExtension(T instance) {

	if (objectFactory == null) {
		return instance;
	}

	try {
		// 循环扩展实例的方法
		for (Method method : instance.getClass().getMethods()) {
			// 如果不是setter方法则继续循环
			if (!isSetter(method)) {
				continue;
			}
			/**
			  * Check {@link DisableInject} to see if we need auto injection for this property
			  */
			// 如果方法上有DisableInject注解,则继续循环
			if (method.getAnnotation(DisableInject.class) != null) {
				continue;
			}
			// 获取方法的第一个参数的类型
			Class<?> pt = method.getParameterTypes()[0];
			// 如果方法的第一个参数不是基础类型,就继续循环
			if (ReflectUtils.isPrimitives(pt)) {
				continue;
			}

			// 所以走到这里的情况是set方法只有一个参数,并且参数是public的
			try {
				// 根据setXXX方法名,获取属性名称
				String property = getSetterProperty(method);
				// 这里主要是通过getExtension 寻找 与参数pt的Class类型相同的 且 名称相同的 扩展类实例,如果能找到,就通过invoke把找到的object设置进去
				// objectFactory有三种实现,后面再说
				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;
}

// 根据setXXX方法名,获取属性名称
private String getSetterProperty(Method method) {
	return method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
}

20.initExtension-初始化扩展实例

private void initExtension(T instance) {
	if (instance instanceof Lifecycle) {
		Lifecycle lifecycle = (Lifecycle) instance;
		lifecycle.initialize();
	}
}

到这里,getExtension方法才算全部执行完成

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值