在学习SPI之前先去学习策略模式,因为这是一样一样的、、
学习顺序
1、先举个官网的小栗子
2、介绍SPI源码实现
3、结合Protocol的export(Invoker<T> invoker)接口分析DubboProtocol和rmiProtocol是怎么做到自适应的
首先,我们定义一个接口,名称为 Robot。
@SPI public interface Robot { void sayHello(); }接下来定义两个实现类,分别为 OptimusPrime 和 Bumblebee。
public class OptimusPrime implements Robot { @Override public void sayHello() { System.out.println("Hello, I am Optimus Prime."); } } public class Bumblebee implements Robot { @Override public void sayHello() { System.out.println("Hello, I am Bumblebee."); } }接下来 META-INF/services 文件夹下创建一个文件,名称为 Robot 的全限定名 org.apache.spi.Robot。文件内容为实现类的全限定的类名,如下:
optimusPrime = org.apache.spi.OptimusPrime bumblebee = org.apache.spi.Bumblebee做好所需的准备工作,接下来编写代码进行测试。
Dubbo SPI 是通过键值对的方式进行配置,这样我们可以按需加载指定的实现类。另外,在测试 Dubbo SPI 时,需要在 Robot 接口上标注 @SPI 注解。下面来演示 Dubbo SPI 的用法:
public class DubboSPITest { @Test public void sayHello() throws Exception { ExtensionLoader<Robot> extensionLoader = ExtensionLoader.getExtensionLoader(Robot.class); Robot optimusPrime = extensionLoader.getExtension("optimusPrime"); optimusPrime.sayHello(); Robot bumblebee = extensionLoader.getExtension("bumblebee"); bumblebee.sayHello(); } }测试结果如下:
题外话:是不是活脱脱的策略模式
1、ExtensionLoader.getExtensionLoader(Class<T> type)
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { if (type == null) { throw new IllegalArgumentException("Extension type == null"); } if (!type.isInterface()) { throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!"); } if (!withExtensionAnnotation(type)) { throw new IllegalArgumentException("Extension type (" + type + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!"); } //从缓存中获取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; } private ExtensionLoader(Class<?> type) { this.type = type; objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); }解释:
1、先从缓存获取ExtensionLoader对象,如果没有就去创建并加入缓存
2、初始化ExtensionLoader对象之前老套路先初始化ExtensionFactory对象
我们来看getAdaptiveExtension():获取自适应拓展
/** * 获取自适应拓展 * @return */ @SuppressWarnings("unchecked") public T getAdaptiveExtension() { //冲缓存中获取自适应拓展 Object instance = cachedAdaptiveInstance.get(); if (instance == null) { if (createAdaptiveInstanceError != null) { throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); } synchronized (cachedAdaptiveInstance) { instance = cachedAdaptiveInstance.get(); if (instance == null) { try { //创建自适应拓展放入缓存 instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { createAdaptiveInstanceError = t; throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t); } } } } return (T) instance; }解释:
1、老套路先从缓存中获取自适应拓展,如果没有创建放入缓存,进入createAdaptiveExtension()
/** * 创建自适应拓展 * @return */ @SuppressWarnings("unchecked") private T createAdaptiveExtension() { try { //获取自适应拓展,进行依赖注入 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e); } }解释:
1、inJectExtension():这个是将自适应拓展进行依赖注入IOC
2、我们进入getAdaptiveExtensionClass():获取自适应拓展类
private Class<?> getAdaptiveExtensionClass() { //加载拓展类 getExtensionClasses(); if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } return cachedAdaptiveClass = createAdaptiveExtensionClass(); }解释:
1、加载拓展类
2、创建自适应拓展类
先看getExtensionClasses():加载拓展类
/** * 加载拓展类 * @return */ private Map<String, Class<?>> getExtensionClasses() { //从缓存中获取 Map<String, Class<?>> classes = cachedClasses.get(); if (classes == null) { synchronized (cachedClasses) { classes = cachedClasses.get(); if (classes == null) { //从文件中加载拓展类 classes = loadExtensionClasses(); cachedClasses.set(classes); } } } return classes; } /** * synchronized in getExtensionClasses * */ private Map<String, Class<?>> loadExtensionClasses() { //加载默认 cacheDefaultExtensionName(); //加载默认文件夹下的拓展类 Map<String, Class<?>> extensionClasses = new HashMap<>(); loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName()); loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName()); loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName()); loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); return extensionClasses; }解释:
1、从缓存获取,如果没有穿件加入缓存
2、loadExtensionClasses()里边的cacheDefaultExtensionName():加载默认的拓展类
3、价值默认文件夹下的拓展类,可以看到Dubbo有很多的默认文件夹里边以Key=value存储,如
我们来看cacheDefaultExtensionName():加载默认的拓展类
/** * extract and cache default extension name if exists * 加载默认的拓展类 */ private void cacheDefaultExtensionName() { //获取SPI注解 final SPI defaultAnnotation = type.getAnnotation(SPI.class); if (defaultAnnotation == null) { return; } 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)); } if (names.length == 1) { cachedDefaultName = names[0]; } } }解释:
1、先获取这个类是否有@SPI注解,如果没有直接返回,如果有并且只有一个value值,把value值放入缓存
我们再回过头来看getAdaptiveExtensionClass():createAdaptiveExtensionClass()动态创建自适应类
private Class<?> createAdaptiveExtensionClass() { //构建自适应拓展代码 String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate(); ClassLoader classLoader = findClassLoader(); //获取编译器实现类 org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); //变异代码生成class return compiler.compile(code, classLoader); }看注释,我们再看generater(),生成源代码,看注释
/** * generate and return class code * 生成并返回自适应拓展类的源码 */ public String generate() { // no need to generate adaptive class since there's no adaptive method found. //方法上必须要有Adaptive注解 if (!hasAdaptiveMethod()) { throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!"); } StringBuilder code = new StringBuilder(); //生成package包路径 code.append(generatePackageInfo()); //生成import code.append(generateImports()); //生成类名代码 code.append(generateClassDeclaration()); //生成方法 Method[] methods = type.getMethods(); for (Method method : methods) { code.append(generateMethod(method)); } code.append("}"); if (logger.isDebugEnabled()) { logger.debug(code.toString()); } return code.toString(); }我们回头看这个方法:injectExtension(T instance),为生成的拓展类,检查是否有Setter方法进行Setter注入,看代码注释
/** * IOC注入 * @param instance * @return */ 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 */ //如果有自动注入跳过 if (method.getAnnotation(DisableInject.class) != null) { continue; } Class<?> pt = method.getParameterTypes()[0]; if (ReflectUtils.isPrimitives(pt)) { continue; } try { //获取Setter方法属性 String property = getSetterProperty(method); //获取依赖对象 Object object = objectFactory.getExtension(pt, property); if (object != null) { //通过反射调用Setter方法注入依赖 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; }总结:到此为止,已生成ExtensionLoader里边包含:第一步如此Class类型的ExtensionFactory<Class>
然后我们进入ExtensionLoader:getExtension(String name):根据配置的name获取拓展类对象
/** * Find the extension with the given name. If the specified name is not found, then {@link IllegalStateException} * will be thrown. * 根据名称获取推展类对象 */ @SuppressWarnings("unchecked") public T getExtension(String name) { if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("Extension name == null"); } //获取默认的拓展实现类 if ("true".equals(name)) { return getDefaultExtension(); } //用于持有目标对象 final Holder<Object> holder = getOrCreateHolder(name); Object instance = holder.get(); if (instance == null) { synchronized (holder) { instance = holder.get(); if (instance == null) { //创建目标类对象 instance = createExtension(name); holder.set(instance); } } } return (T) instance; }进入createExtension(name):创建目标类对象
/** * 创建拓展类对象 * @param name * @return */ @SuppressWarnings("unchecked") private T createExtension(String name) { //从文件加载所有的拓展类,得到key,value对应关系 Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { //创建实例放入缓存 EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } //向实例中注入依赖IOC injectExtension(instance); Set<Class<?>> wrapperClasses = cachedWrapperClasses; if (CollectionUtils.isNotEmpty(wrapperClasses)) { for (Class<?> wrapperClass : wrapperClasses) { //创建wrapper对象,并将对象注入实例 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); } }解释:
1、查询缓存是否有目标类对象,如果没有创建并放入缓存
2、向对象中注入依赖IOC,是否有包装类对象,如果有创建包装类,并将该对象注入到包装类
我们来看injectExtension(instance):向对象实例中注入依赖
/** * IOC注入 * @param instance * @return */ 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 */ //如果有自动注入跳过 if (method.getAnnotation(DisableInject.class) != null) { continue; } Class<?> pt = method.getParameterTypes()[0]; if (ReflectUtils.isPrimitives(pt)) { continue; } try { //获取Setter方法属性 String property = getSetterProperty(method); //获取依赖对象 Object object = objectFactory.getExtension(pt, property); if (object != null) { //通过反射调用Setter方法注入依赖 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; }解释:
1、通过反射获取所有方法,检查是否有Setter方法,如果没有跳过
2、检查是否有自动注入,有跳过
3、获取Setter属性,获取依赖对象,注入
总结:到此为止,已经创建拓展类对象实例,并将依赖注入对象,随时可调用方法
debug的时候我是拿这个例子调试的-随便找的:org.apache.dubbo.rpc.cluster.support.AbstractClusterInvokerTest#testDonotSelectAgainAndNoCheckAvailable
公众号主要记录各种源码、面试题、微服务技术栈,帮忙关注一波,非常感谢