dubbo源码系列2——spi源码解读(下)

        今天是2021年10月1号,在此祝伟大的祖国母亲生日快乐,繁荣昌盛!

        上一节对sdk spi机制从源码角度进行了分析,文末留下思考:jdk spi有什么缺点?总结如下:

  • 无法按需加载

    ServiceLoader通过LazyIterator实现延迟加载,但是加载时仍然是遍历所有的类进行实例化,无法按需加载;

  • 多线程非安全

    ServiceLoader方法都是static,在并发时可能出现意想不到的线程安全问题;

        针对以上问题,dubbo在借鉴sdk spi的基础上,通过分离配置加载和实例化实现按需加载,并且提供了ioc以及aop,进行功能增强。接下来看看dubbo如何实现相关功能?本节安排如下:

  1. demo
  2. 拓展点分析
  3. ioc
  4. aop
  5. 总结

1、demo

1.1、接口

//运动接口

package xu.jiang.hua.dubbo.api.service;
import org.apache.dubbo.common.extension.SPI;
@SPI("volleyball")
public interface Sport {
     
    
    public void play();
}

定义Sport接口,并且指定默认实现为volleyball.

@SPI
public interface Drink {
     
    void drink();
}

1.2、实现

//篮球实现

package xu.jiang.hua.dubbo.api.service.impl;
import xu.jiang.hua.dubbo.api.service.Drink;
import xu.jiang.hua.dubbo.api.service.Sport;
public class BasketBallSport implements Sport {
     

    private Drink drink;
    public void setDrink(Drink drink) {
     
        this.drink = drink;
    }

    @Override
    public void play() {
     

        System.out.print("运动前喝点饮料补充养分:");
        drink.drink();
        System.out.println("play basketball");
    }
}

//排球实现

package xu.jiang.hua.dubbo.api.service.impl;

import xu.jiang.hua.dubbo.api.service.Sport;

public class VolleyballSport implements Sport {
     
    @Override
    public void play() {
     
        System.out.println("play volleyballSport");
    }
}

//FootBallSport

package xu.jiang.hua.dubbo.api.service.impl;

import org.apache.dubbo.common.extension.Adaptive;
import xu.jiang.hua.dubbo.api.service.Sport;

@Adaptive
public class FootBallSport implements Sport {
     

    @Override
    public void play() {
     

        System.out.println("play football");
    }
}

并通过@Adaptive标示FootBallSport 为Sport的自适应类。

//运动切面

package xu.jiang.hua.dubbo.api.service.impl;
import xu.jiang.hua.dubbo.api.service.Sport;

public class SportWrapper1 implements Sport {
     

    private Sport sport;

    public SportWrapper1(Sport sport) {
     
        this.sport = sport;
    }
    @Override
    public void play() {
     
        System.out.println("运动前1");
        sport.play();
        System.out.println("运动后1");
    }
}

//饮料实现

package xu.jiang.hua.dubbo.api.service.impl;

import org.apache.dubbo.common.extension.Adaptive;
import xu.jiang.hua.dubbo.api.service.Drink;

@Adaptive
public class MineralWater implements Drink {
     
    @Override
    public void drink() {
     
        System.out.println("喝矿泉水");
    }
}

并通过@Adaptive标示MineralWater为Drink的自适应类。

1.3、配置

  • xu.jiang.hua.dubbo.api.service.Sport
    basketBall=xu.jiang.hua.dubbo.api.service.impl.BasketBallSport
    volleyball=xu.jiang.hua.dubbo.api.service.impl.VolleyballSport
    footBall=xu.jiang.hua.dubbo.api.service.impl.FootBallSport
    xu.jiang.hua.dubbo.api.service.impl.SportWrapper1

  • xu.jiang.hua.dubbo.api.service.Drink
    mineralWater=xu.jiang.hua.dubbo.api.service.impl.MineralWater

1.4、运行结果

public class MainTest {
     

    public static void main(String[] args) {
     


        System.out.println("...........getExtension............");
        Sport basketBall = ExtensionLoader.getExtensionLoader(Sport.class).getExtension("basketBall");
        basketBall.play();

        System.out.println("...........getDefaultExtension............");
        Sport defaultSport = ExtensionLoader.getExtensionLoader(Sport.class).getDefaultExtension();
        defaultSport.play();


        System.out.println("...........getAdaptiveExtension............");
        Sport adaptiveSport = ExtensionLoader.getExtensionLoader(Sport.class).getAdaptiveExtension();
        adaptiveSport.play();

    }
}

dubbo源码系列2——spi源码解读(下)_第1张图片
        从执行结果来看,basketBall这个拓展点的方法执行前后有SportWrapper1类进行拦截,同时通过dubbo spi机制注入Drink接口。
        因Sport接口上@SPI(“volleyball”)上指定了默认实现,因此getDefaultExtension返回VolleyballSport;

2、拓展点分析

        下面以上面demo为例深入源码分析内部实现逻辑。

2.1、getExtensionLoader

可以看到加载任何拓展点都需要先执行getExtensionLoader

    public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
     
        //省略非关键代码
        ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        if (loader == null) {
     
            //new ExtensionLoader(type)
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        }
        return loader;
    }

继续分析new ExtensionLoader(type),如下:

    private ExtensionLoader(Class<?> type) {
     
        this.type = type;

        /** 逻辑解读:
         *  1、传入的type为非ExtensionFactory时,则执行ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
         *  2、则再次调用new ExtensionLoader(Class type),则再次执行ExtensionLoader的构造函数,此时type为ExtensionFactory,objectFactory为null;
         *  3、根据返回的ExtensionLoader,再执行方法getAdaptiveExtension;
         *  4、加载META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory的内容,里面有SpiExtensionFactory和AdaptiveExtensionFactory,
         *     因AdaptiveExtensionFactory被@Adaptive注解标注,则getAdaptiveExtension返回AdaptiveExtensionFactory的实例对象
         *  5、接下来对AdaptiveExtensionFactory进行实例化,AdaptiveExtensionFactory属性factories仅有SpiExtensionFactory(通过cachedClasses获取)
         */
        objectFactory =
                (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

        对type为非ExtensionFactory生成的ExtensionLoader,objectFactory为SpiExtensionFactory。

2.2、getExtension

    public T getExtension(String name, boolean wrap) {
     
        //省略非关键代码
        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, wrap);
                    holder.set(instance);
                }
            }
        }
        return (T) instance;
    }

解析来分析createExtension方法(重点

 private T createExtension(String name, boolean wrap) {
     
        //A、加载配置返回map,并根据name获取对应的类
        Class<?> clazz = getExtensionClasses().get(name);
        if (clazz == null || unacceptableExceptions.contains(name)) {
     
            throw findException(name);
        }
        try {
     
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
     
          //实例化
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            //B、ioc注入
            injectExtension(instance);

            //C、aop处理
            if (wrap) {
     

                List<Class<?>> wrapperClassesList = new ArrayList<>();
                //找出所有的Wrapper并排序
                if (cachedWrapperClasses != null) {
     
                    wrapperClassesList.addAll(cachedWrapperClasses);
                    wrapperClassesList.sort(WrapperComparator.COMPARATOR);
                    Collections.reverse(wrapperClassesList);//倒叙List
                }

                if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
     
                    for (Class<?> wrapperClass : wrapperClassesList) {
     
                        //获取wrapper注解,如果为非空,则需要判断注解的上的match和mismatch是否与当前name匹配。如果不匹配,不生成aop实例
                        Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
                        if (wrapper == null
                                || (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {
     
                            /**
                             * wrapperClass.getConstructor(type).newInstance(instance) 实例化warpper类(aop类),将新生成的
                             * 实例赋值给instance,从而实现aop
                             *
                             * injectExtension 对warpper类实现ioc set
                             */
                            instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                        }
                    }
                }
            }

            initExtension(instance);
            return instance;
        } catch (Throwable t) {
     
         //省略非关键代码
        }
    }

createExtension方法主要分成以下三部分:

  • getExtensionClasses加载配置文件
  • ioc处理
  • aop处理

将加载配置和实例化分开,从而实现按需实例化,避免不必要的资源浪费(相比jdk spi的改进点)。先接下来看看内部如何实现的?

2.3、getExtensionClasses

      private Map<String, Class<?>> loadExtensionClasses() {
     
        //A、加载当前接口的默认实现类
        cacheDefaultExtensionName();

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

        /**B、加载配置文件
         * 
         * 策略模式,分别加载以下路径:
         * 1、META-INF/dubbo/internal/
         * 2、META-INF/dubbo
         * 3、META-INF/Service
         */
        for (LoadingStrategy strategy : strategies) {
     
            loadDirectory(extensionClasses, strategy.directory(), type.getName(), 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;
    }

第一部分默认实现类的处理:

  private void cacheDefaultExtensionName() {
     
        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中
                cachedDefaultName = names[0];
            }
        }
    }

比如Sport有默认实现volleyball,如下所示:
dubbo源码系列2——spi源码解读(下)_第2张图片
再看第二部分加载配置文件,目前支持以下三种路径:

  • META-INF/dubbo/internal/
  • META-INF/dubbo
  • META-INF/Service
    为了兼容dubbo移交给apache成为旗下的顶级项目,同时也会将type接口名中的org.apache换成com.alibaba。接下来看loadDirectory方法:
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
                               boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) {
     
        String fileName = dir + type;
         //省略非关键代码
            if (urls != null) {
     
                while (urls.hasMoreElements()) {
     
                    java.net.URL resourceURL = urls.nextElement();
                    //加载Resourece
                    loadResource(extensionClasses, classLoader, resourceURL, overridden, excludedPackages);
                }
            }
        } catch (Throwable t) {
     
          //省略非关键代码
        }
    }

接下来看loadResource方法

 private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
                              java.net.URL resourceURL, boolean overridden, String... excludedPackages) {
     
        try {
     
            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;//如果无=,则认为是当前接口的warpper类
                            }
                            //加载的类非空且不在排除的类集合里面,则执行loadClass
                            if (StringUtils.isNotEmpty(clazz) && !isExcluded(clazz, excludedPackages)) {
     
                                loadClass(extensionClasses, resourceURL, Class.forName(clazz, true, classLoader), name, overridden);
                            }
                        } catch (Throwable t) {
     
                      //省略非关键代码
                        }
                    }
                }
            }
        } catch (Throwable t) {
     
          //省略非关键代码
        }
    }

loadResource说明:依次读取每行,过滤掉注释内容,然后判断当前行是否包含=。如果不包含,则认为该行是该接口Wrapper类(aop实现类),继续看loadClass方法:

   private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name,
                           boolean overridden) throws NoSuchMethodException {
     
            //省略关键代码
            //A、自适应类
        if (clazz.isAnnotationPresent(Adaptive.class)) {
     
            cacheAdaptiveClass(clazz, overridden);//cachedAdaptiveClass
            //B、判断是否为wrapper类—判断该类是否存在一个参数为该接口的构造函数。如存在,则认为为wrapper类
        } else if (isWrapperClass(clazz)) {
     
            cacheWrapperClass(clazz);//cachedWrapperClasses
        } else {
     
         //省略关键代码
            String[] names = NAME_SEPARATOR.split(name);//一个类可以当做多个拓展点,因此进行切分
            if (ArrayUtils.isNotEmpty(names)) {
     
                cacheActivateClass(clazz, names[0]);//cachedActivates
                for (String n : names) {
     
                    cacheName(clazz, n);
                    //存入map
                    saveInExtensionClass(extensionClasses, clazz, n, overridden);
                }
            }
        }
    }

loadClass可以拆解成三部分:

  • Adaptive注解处理
    如果该类被@Adaptive注解标注,则将该类保存在以下爱属性中。
    private volatile Class cachedAdaptiveClass = null;

  • Wrapper类处理

    private boolean isWrapperClass(Class<?> clazz) {
     
        try {
     
            //通过加载判断是否存在带接口的构造函数
            clazz.getConstructor(type);
            return true;
        } catch (NoSuchMethodException e) {
     
            return false;
        }
    }

通过判断当前类是否存在以该接口为参数的构造函数。如果存在则认为为wrapper类,如果存在则将该列保存在private Set> cachedWrapperClasses;

  • 其他处理
    将name进行切分,分别存入Map> extensionClasses中,如下所示:
    private void saveInExtensionClass(Map<String, Class<?>> extensionClasses, Class<?> clazz, String name, boolean overridden) {
     
        Class<?> c = extensionClasses.get(name);
        if (c == null || overridden) {
     
            extensionClasses.put(name, clazz);
        } else if (c != clazz) {
     
            // duplicate implementation is unacceptable
            unacceptableExceptions.add(name);
            String duplicateMsg =
                    "Duplicate extension " + type.getName() + " name " + name + " on " + c.getName() + " and " + clazz.getName();
            logger.error(duplicateMsg);
            throw new IllegalStateException(duplicateMsg);
        }
    }

总结一下getExtensionClasses加载配置后的保存情况:

  • 接口默认实现类保存在
private String cachedDefaultName;
  • 被@Adaptive标注的实现类
 private volatile Class<?> cachedAdaptiveClass = null;
  • warpper类
private Set<Class<?>> cachedWrapperClasses;
  • 其他类
 private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();

cachedClasses则作为getExtensionClasses的结果返回。

3、ioc

        ioc处理位于createExtension方法中,回顾一下createExtension方法:

   private T createExtension(String name, boolean wrap) {
     
        //加载配置,并根据name返回对应的类
        Class<?> clazz = getExtensionClasses().get(name);
        if (clazz == null || unacceptableExceptions.contains(name)) {
     
            throw findException(name);
        }
        try {
     
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
     
                //实例化
                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            //ioc注入
            injectExtension(instance);

    //省略其他
    }

         通过getExtensionClasses将配置加载到map中并根据name获取对应类,然后进行实例化,实例化后执行injectExtension处理ioc。下面看看injectExtension方法:

private T injectExtension(T instance) {
     

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

        try {
     
            for (Method method : instance.getClass().getMethods()) {
     
                if (!isSetter(method)) {
     
                    continue;
                }
                /**
                 * Check {@link DisableInject} to see if we need auto injection for this property
                 */
                //set方法如果不想被ioc使用,则通过注解标示
                if (method.getAnnotation(DisableInject.class) != null) {
     
                    continue;
                }
                Class<?> pt = method.getParameterTypes()[0];
                if (ReflectUtils.isPrimitives(pt)) {
     
                    continue;
                }

                try {
     
                    String property = getSetterProperty(method);
                    //通过type和名字从objectFactory获取
                    Object object = objectFactory.getExtension(pt, property);
                    if (object != null) {
     
                        //反射调用方法
                        method.invoke(instance, object);
                    }
                } catch (Exception e) {
     
                  //省略非关键代码
                }

            }
        } catch (Exception e) {
     
            logger.error(e.getMessage(), e);
        }
        return instance;
    }

        接下来看如何通过objectFactory.getExtension(pt, property)从上下文获取实例。根据ExtensionLoader实例化分析可知,objectFactory为AdaptiveExtensionFactory,如下:
dubbo源码系列2——spi源码解读(下)_第3张图片

    public <T> T getExtension(Class<T> type, String name) {
     
        for (ExtensionFactory factory : factories) {
     
            T extension = factory.getExtension(type, name);
            if (extension != null) {
     
                return extension;
            }
        }
        return null;
    }

此时facory中仅有SpiExtensionFactory,执行getExtension方法返回实例。下面看看getExtension如何执行的?

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);
            /**
             * 如果type仅有一个实现类并且类上有一个@Adaptive标注,此时loader.getSupportedExtensions()
             * 返回为空,则getExtension返回null。为什么?
             */
            if (!loader.getSupportedExtensions().isEmpty()) {
     
                //返回自适应类
                return loader.getAdaptiveExtension();
            }
        }
        return null;
    }

}

分析getAdaptiveExtension:

    public T getAdaptiveExtension() {
     
        Object instance = cachedAdaptiveInstance.get();
              //省略非关键代码      
            synchronized (cachedAdaptiveInstance) {
     
                instance = cachedAdaptiveInstance.get();
                if (instance == null) {
     
                    try {
     
                        //创建adaptiveExtension实例
                        instance = createAdaptiveExtension();
                        cachedAdaptiveInstance.set(instance);
                    } catch (Throwable t) {
     
                        createAdaptiveInstanceError = t;
                        throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
                    }
                }
            }
        }

        return (T) instance;
    }

继续分析createAdaptiveExtension:

    private T createAdaptiveExtension() {
     
        try {
     
            //获取adaptiveExtension类并实例化,然后执ioc
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
     
           //省略非关键代码
        }
    }

重点看getAdaptiveExtensionClass()方法

  private Class<?> getAdaptiveExtensionClass() {
     
        getExtensionClasses();
        //优先使用被@Adaptive标注的类
        if (cachedAdaptiveClass != null) {
     
            return cachedAdaptiveClass;
        }
        //如果当前接口不存在Adaptive注解标注的实现类,那么需要手动编译方法
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }

可以看到ioc注入的实例获取的优先级:

  • @Adaptive标注的类
  • 动态生成自适应类(方法上必须有@Adaptive注解,否则抛异常)。运行时通过传递url指定接口的实现类,如果传递的url未匹配上且有默认实现,则使用默认实现

下面就以以上面两种情况进行演示:

3.1、@Adaptive在类上

@Adaptive
public class MineralWater implements Drink {
     

    @Override
    public void drink(URL url) {
     
        System.out.println("喝矿泉水");
    }
}

dubbo源码系列2——spi源码解读(下)_第4张图片

3.2、@Adaptive在方法上

        将MineralWater上的@Adaptive注解去掉,同时方法加上@Adaptive并设定key为drink,则运行通过url里面map参数指定具体的实现。

@SPI("mineralWater")
public interface Drink {
     

    @Adaptive({
     "drink"})
    void drink(URL url);
}

dubbo源码系列2——spi源码解读(下)_第5张图片

   private Class<?> createAdaptiveExtensionClass() {
     
        //生成代理类时判断方法上是否有@Adaptive注解修饰,如果没有,则抛出异常
        String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
        ClassLoader classLoader = findClassLoader();
        org.apache.dubbo.common.compiler.Compiler compiler =
       //AdaptiveCompiler
        ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
        return compiler.compile(code, classLoader);
    }

3.3、自动生成的自适应类

package xu.jiang.hua.dubbo.api.service;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Drink$Adaptive implements xu.jiang.hua.dubbo.api.service.Drink {
     

public void drink(org.apache.dubbo.common.URL arg0)  {
     

	if (arg0 == null) 
	
	throw new IllegalArgumentException("url == null");
	
	org.apache.dubbo.common.URL url = arg0;
	//因为接口上指定了默认实现为mineralWater,则如果取不到则使用默认的实现
	String extName = url.getParameter("drink", "mineralWater");
	
	if(extName == null) 
		throw new IllegalStateException("Failed to get extension (xu.jiang.hua.dubbo.api.service.Drink) name from url (" + url.toString() + ") use keys([drink])");
		
	xu.jiang.hua.dubbo.api.service.Drink extension = (xu.jiang.hua.dubbo.api.service.Drink)ExtensionLoader.getExtensionLoader(xu.jiang.hua.dubbo.api.service.Drink.class).getExtension(extName);
	
	extension.drink(arg0);
}
}

dubbo源码系列2——spi源码解读(下)_第6张图片
        将生成的自适应类通过反射赋给BasketBallSport实例, 运行时通过URL指定具体的实现:
URL url=URL.valueOf(“http://127.0.0.1”);
url= url.addParameter(“drink”,“mineralWater”);
drink.drink(url);

3.3、ioc总结

        通过injectExtension方法和类上的set方法实现依赖注入,获取的实例的优先级如下:

  • A、@Adaptive标记类生成的实例;
  • B、根据@Adaptive标记的方法自动编译生成自适应类,运行时如果匹配失败且有默认实现类,则使用默认类。

4、aop

aop处理同样位于createExtension方法中,回顾一下createExtension方法:

    private T createExtension(String name, boolean wrap) {
     
            //省略非关键代码          
            //ioc注入
            injectExtension(instance);

            //aop处理
            if (wrap) {
     

                List<Class<?>> wrapperClassesList = new ArrayList<>();
                //找出所有的Wrapper并排序
                if (cachedWrapperClasses != null) {
     
                    wrapperClassesList.addAll(cachedWrapperClasses);
                    wrapperClassesList.sort(WrapperComparator.COMPARATOR);
                    Collections.reverse(wrapperClassesList);//倒叙List
                }

                if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
     
                    for (Class<?> wrapperClass : wrapperClassesList) {
     
                        //获取wrapper注解,如果为非空,则需要判断注解的上的match和mismatch是否与当前name匹配。如果不匹配,不生成aop实例
                        Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
                        if (wrapper == null
                                || (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {
     
                            /**
                             * wrapperClass.getConstructor(type).newInstance(instance) 实例化warpper类(aop类),将新生成的
                             * 实例赋值给instance,从而实现aop
                             *
                             * injectExtension 对warpper类实现ioc set
                             */
                            instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                        }
                    }
                }
            }

            initExtension(instance);
            return instance;
        } catch (Throwable t) {
     
     
        }
    }

        前面getExtensionClasses方法中已经分析过warpper类会保存在

private Set> cachedWrapperClasses;

取出所有的cachedWrapperClasses并排序。接下来重点看
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance))

从warpper类中取出具有接口参数的构造函数,并向构造函数传入当前实例进行warpper类的实例化,然后进行ioc处理(warpper类可能也有依赖注入),然后赋值给instance(前后instance不是同一个对象),如下所示:
dubbo源码系列2——spi源码解读(下)_第7张图片
dubbo源码系列2——spi源码解读(下)_第8张图片
        可以看到instantce不是同一个对象,新生成的instance包含之前的instance。

5、总结

        每个拓展点都会通过getExtensionLoader生成ExtensionLoader实例。

  • getExtension

    getExtension通过传入的name实现按需实例化;

  • getDefaultExtension

    getDefaultExtension返回接口的默认实现, 默认实现的 类名保存在
    private String cachedDefaultName;

  • getAdaptiveExtension
    getDefaultExtension返回接口的自适应类。优先使用@Adaptive标注的类,保存在cachedAdaptiveClass。如果无@Adaptive标记的类,则根据@Adaptive标记的方法自动生成自适应类;

 private volatile Class<?> cachedAdaptiveClass = null;
  • ioc
    获取当前接口getAdaptiveExtension返回实例进行依赖注入;如果getAdaptiveExtension为空且有默认实现,则使用默认实现,否则不注入;

  • aop
    根据getExtensionClasses得到接口的warpper类集合实现链式增强并作为新实例返回。

  private Set<Class<?>> cachedWrapperClasses;

你可能感兴趣的:(dubbo,dubbo,spi,架构)