@Test public void test1(){ ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); AdaptiveExt adaptiveExtension = loader.getExtension("dubbo"); URL url = URL.valueOf("test://localhost/test"); adaptiveExtension.echo("d", url); } public class DubboAdaptiveExt implements AdaptiveExt { // dubbo中有依赖AdaptiveExt类型的变量 private AdaptiveExt adaptiveExt; public void setAdaptiveExt(AdaptiveExt adaptiveExt) { this.adaptiveExt = adaptiveExt; } @Override public String echo(String msg, URL url) { System.out.println(this.adaptiveExt.echo(msg, url)); return "dubbo"; } }
// 此时ThriftAdaptiveExt上面是标注了@Adaptive注解的 @Adaptive public class ThriftAdaptiveExt implements AdaptiveExt { @Override public String echo(String msg, URL url) { return "thrift"; } }
Spring的IOC中,给生成的bean注入依赖,是调用context.getBean(name)去得到要注入的bean.Dubbo的IOC相似,它经过ExtensionFactory类型的变量objectFactory去dubbo中获取bean,核心代码objectFactory.getExtension(pt, property)
.下面先分析一下objectFactory的建立过程.objectFactory须要用到SpringExtensionFactory和SpiExtensionFactory
.先看一下ExtenionFactory的实现类,以下图.下面经过源码分析objectFactory的生成过程.spring
这里的getExtensionLoader()详细分析能够参见: Dubbo的SPI机制1-SPI简单分析segmentfault
ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> 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; } private ExtensionLoader(Class<?> type) { this.type = type; // 这里的type是AdaptiveExt.class,因此会执行后面的代码,加载并建立SpiExtensionFactory // 和SpringExtensionFactory objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); }
public T getAdaptiveExtension() { Object instance = cachedAdaptiveInstance.get(); if (instance == null) { if (createAdaptiveInstanceError == null) { synchronized (cachedAdaptiveInstance) { instance = cachedAdaptiveInstance.get(); if (instance == null) { try { // 建立自适应拓展代理类对象并放入缓存,这里建立的就是ExtensionFactory的自适应拓展对象 instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { // 抛异常 } } } } } return (T) instance; }
private T createAdaptiveExtension() { try { // 分为3步:1是建立自适应拓展代理类Class对象,2是经过反射建立对象,3是给建立的对象按需依赖注入 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { // 抛异常 } }
getExtensionClasses()方法详细分析能够参见: Dubbo的SPI机制1-SPI简单分析缓存
private Class<?> getAdaptiveExtensionClass() { // 这里前面文章已经分析过了,它会去加载默认目录下的ExtensionFactory的实现类,总共有3个,目录是 // META-INF/dubbo/internal/,该目录对应两个文件,文件内容见下,因为AdaptiveExtensionFactory上面 // 标注了@Adaptive注解,因此它优先级最高,它就是ExtensionFactory的默认实现类 getExtensionClasses(); // 若是有标注了@Adaptive注解实现类,那么cachedAdaptiveClass不为空,直接返回 if (cachedAdaptiveClass != null) { // 这里直接返回,cachedAdaptiveClass = AdaptiveExtensionFactory.class return cachedAdaptiveClass; } // 不会再走这一步 return cachedAdaptiveClass = createAdaptiveExtensionClass(); }
文件1内容: // 其中AdaptiveExtensionFactory上面标注了@Adaptive注解 adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory 文件2内容: spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
@Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory {
// 分析完了getAdaptiveExtensionClass(),它是返回AdaptiveExtensionFactory,接下来newInstance会 // 调用它默认的构造方法 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); @Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory { // 里面维护SpringExtensionFactory和SpiExtensionFactory private final List<ExtensionFactory> factories; public AdaptiveExtensionFactory() { ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); List<ExtensionFactory> list = new ArrayList<ExtensionFactory>(); for (String name : loader.getSupportedExtensions()) { // 分别给SpringExtensionFactory和SpiExtensionFactory建立对象并放入list中 list.add(loader.getExtension(name)); } factories = Collections.unmodifiableList(list); } }
// 上面已经分析过了第一行代码,这里面会建立ExtensionFactory类型的变量objectFactory,这里面维护了一个list, // list里面有SpringExtensionFactory和SpiExtensionFactory类型的实例,Dubbo的IOC获取bean就是经过这两个 // 变量去获取的 ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); AdaptiveExt adaptiveExtension = loader.getExtension("dubbo"); public T getExtension(String name) { // 删去一些代码 if (instance == null) { synchronized (holder) { instance = holder.get(); if (instance == null) { // 建立拓展实例 instance = createExtension(name); holder.set(instance); } } } return (T) instance; }
private T createExtension(String name) { // 从配置文件中加载全部的拓展类,可获得“配置项名称”到“配置类”的映射关系表 // 这里咱们指定了名字dubbo,并非经过getAdaptiveExtension方法去得到自适应拓展类,这点要区分 // 因此这里拿到的是com.alibaba.dubbo.demo.provider.adaptive.impl.DubboAdaptiveExt Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { // 也是尝试先从缓存获取,获取不到经过反射建立一个并放到缓存中 T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { // 这里直接经过反射建立DubboAdaptiveExt的实例,而后给他依赖注入 EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } // 依赖注入 injectExtension(instance); return instance; } }
private T injectExtension(T instance) { // 这里为了排版好看,删去一些异常捕捉抛出代码 // objectFactory就是咱们前面分析的,它里面维护了SpringExtensionFactory和SpiExtensionFactory类型的实例 if (objectFactory != null) { // 遍历DubboAdaptiveExt实例的全部方法,寻找set开头且参数为1个,且方法权限为public的方法 for (Method method : instance.getClass().getMethods()) { if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())) { // 获取参数类型,这里是AdaptiveExt.class Class<?> pt = method.getParameterTypes()[0]; // 获取属性名,这里是adaptiveExt String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : ""; // 获取容器中AdaptiveExt.class类型的名字为adaptiveExt的实例 Object object = objectFactory.getExtension(pt, property); // 获取以后经过反射赋值 if (object != null) { method.invoke(instance, object); } } } } return instance; }
@Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory { private final List<ExtensionFactory> factories; @Override public <T> T getExtension(Class<T> type, String name) { // 遍历factory中全部的ExtensionFactory,先从SpiExtensionFactory中获取,获取不到在去Spring容器中获取 for (ExtensionFactory factory : factories) { T extension = factory.getExtension(type, name); if (extension != null) { return extension; } } return null; } }
这里获取自适应拓展能够参考: Dubbo的SPI机制分析2-Adaptive详解ide
public class SpiExtensionFactory implements ExtensionFactory { @Override public <T> T getExtension(Class<T> type, String name) { if (type.isInterface() && type.isAnnotationPresent(SPI.class)) { ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type); if (!loader.getSupportedExtensions().isEmpty()) { // 先看SpiExtensionFactory怎么获取,它是经过getAdaptiveExtension()去自适应获取,根本 // 没有用到name,因此这里返回ThriftAdaptiveExt的实例 return loader.getAdaptiveExtension(); } } return null; } }
public class SpringExtensionFactory implements ExtensionFactory { // 能够看到Spring是先根据名字去取,取不到再根据类型去取 @Override public <T> T getExtension(Class<T> type, String name) { 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); } } return null; } }
// 因此这段代码输出:thrift @Test public void test1(){ ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); AdaptiveExt adaptiveExtension = loader.getExtension("dubbo"); URL url = URL.valueOf("test://localhost/test"); adaptiveExtension.echo("d", url); }
/** * 测试经过URL依赖注入,将ThriftAdaptiveExt类上面的注解注释掉,同时给AdaptiveExt方法加上注解@Adaptive("t") */ @Test public void test5(){ ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); Map<String, String> map = new HashMap<>(); // t这个key就是根据@Adaptive("t")定的,二者要一致 map.put("t", "cloud"); URL url = new URL("", "", 1, map); AdaptiveExt adaptiveExtension = loader.getExtension("dubbo"); adaptiveExtension.echo(" ", url); }
上述代码输出spring cloud,建立完DubboAdaptiveExt的实例给其注入依赖时,调用injectExtension(instance),由于没有了@Adaptive标注的类,因此须要Dubbo本身生成自适应拓展代理类Class,生成过程能够参考: Dubbo的SPI机制分析2-Adaptive详解.生成的代理类中有这样一句关键代码: String extName = url.getParameter("t", "dubbo")
,由于url中有这个t参数,因此最后会调用cloud所对应的SpringCloudAdaptiveExt的echo方法,输出spring cloud.源码分析