Dubbo-SPI源码看这篇就够了

JAVA SPI 与API 对比

  • SPI的全称是Service Provider Interface,是Java提供的可用于第三方实现和扩展的机制,通过该机制,我们可以实现解耦,SPI接口方负责定义和提供默认实现,SPI调用方可以按需扩展
  • API的全称是Application Programming Interface,广义上来看就是接口,负责程序与程序之间进行协作的通道,就好比上面给的例子,【我们封装好了一套服务,通过API的形式提供给他人使用,别人使用API就能得到想要的】

所以他们俩的区别就很明显了,API的调用方只能依赖使用提供方的实现,SPI就如同可定制化的API一样,调用方可以自定义实现替换API提供的默认实现

public interface Car {
    
    @Adaptive
    String getCarName(URL url);
    
    String sayHell();
    
    
}

public class BlackCar implements Car {
    
    @Override
    public String getCarName(URL url) {
        return "black";
    }
    
    @Override
    public String sayHell() {
        return null;
    }
}

public class SpiTest {
    public static void main(String[] args) {
        
        // javaSPI
        ServiceLoader<Car> cars = ServiceLoader.load(Car.class);
        for (Car car : cars) {
            System.out.println(car.getCarName(null));
        }
}
// 需要在classpath:META-INFO.services 下配置一个与接口全类名的文件(com.spi.Car)
// 内容: com.spi.BlackCar
//       com.spi.RedCar

为什么Dubbo还要自己搞SPI?

javaSPI 的局限性:
1、没法给实现类起别名
2、没法实现包装类。类似AOP的原理
3、没法实现自动注入
4、没法实现按需加载。一次性就会加载配置文件中配置的所有类

Dubbo SPI案例演示

public class SpiTest {
    public static void main(String[] args) {

        ExtensionLoader<Car> extensionLoader = ExtensionLoader.getExtensionLoader(Car.class);
        Car person = extensionLoader.getExtension("black");  // BlackPerson

        System.out.println(c.getCarName());  // 代理逻辑
    }

    
public class CarWrapper implements Car {

    private Car car;

    public CarWrapper(Car car) {
        this.car = car;
    }

    @Override
    public String getCarName() {
        System.out.println("wrapper...");
        return car.getCarName();
    }

    @Override
    public String sayHell() {
        return null;
    }
}
    

public class BlackCar implements Car {

    @Override
    public String getCarName() {
        return "black";
    }

    @Override
    public String sayHell() {
        return null;
    }
}

@SPI
public interface Car {

    
    String getCarName();

    String sayHell();
}

red=com.spi.RedCar
black=com.spi.BlackCar
com.spi.CarWrapper

wrapper...
black

使用:
1、@SPI 注解需要打在接口上
2、META-INFO.dubbo下需要创建一个与接口全类名相同的文件
3、配置文件内需要配置实现类全类名
4、Wrapper类(类似AOP)需要通过有参构造方法来注入

Dubbo SPI主流程源码解析

大致梳理流程:
1、根据指定的接口加载配置文件
2、根据配置文件加载对应的类 缓存起来
3、根据加载的类按需反射生成对象 缓存起来
4、完成自动注入

ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(Car.class);

// 该方法就是生成一个Loader对象其中包括指定的接口
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<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;
}

Car car = extensionLoader.getExtension(“red”);

@SuppressWarnings("unchecked")
public T getExtension(String name) {
    if (StringUtils.isEmpty(name)) {
        throw new IllegalArgumentException("Extension name == null");
    }
    // 获取默认扩展类 @SPI 注解上标注的value
    if ("true".equals(name)) {
        return getDefaultExtension();
    }
    
    // 为什么要用一个holder来包装?
    // 思考: 要加锁,如果不用holder来包装的话锁的对象不好弄。
    // 因为一开始创建都是null会导致全都拿null来当锁。就单线程了。
    // 如果直接拿name当锁不优雅
    final Holder<Object> holder = getOrCreateHolder(name);
    Object instance = holder.get();
    
    // 如果有两个线程同时来获取同一个name的扩展点对象,那只会有一个线程会进行创建
    if (instance == null) {
        synchronized (holder) { // 一个name对应一把锁
            instance = holder.get();
            if (instance == null) {
                // 创建扩展点实例对象
                instance = createExtension(name);   // 创建扩展点对象
                holder.set(instance);
            }
        }
    }
    return (T) instance;
    }

创建对象

instance = createExtension(name);

private T createExtension(String name) {
        // 获取扩展类  {name: Class}  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);

            // AOP,cachedWrapperClasses无序
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (CollectionUtils.isNotEmpty(wrapperClasses)) {
                for (Class<?> wrapperClass : wrapperClasses) {
                    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);
        }
    }

加载dubbo-spi配置文件

1、读取META-INF下 的配置文件加载类
2、将类分几种情况
2.1 接口上@SPI 注解value 为默认实现类extensionLoader.getExtension(“true”) 既可直接获取默认实例
2.2 实现类上加了@Adaptive 注解,当调用extensionLoader.getActivateExtension()既可直接获取自适应实例。
2.3 有 一个有参构造函数(参数就是该接口)的为wapper类
2.4 剩下的就是普通的一个实现类

getExtensionClasses() 这里终于去加载配置文件了
getExtensionClasses
– loadExtensionClasses
– loadDirectory

   private Map<String, Class<?>> loadExtensionClasses() {
        // cache接口默认的扩展类
        cacheDefaultExtensionName();
        // 这里都是调用同一个方法。只是路径传的不同。这些路径都是固定的就包括了META-INF.dubbo
        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;
    }

// 接口的@SPI注解上可以制定一个默认的实现类
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 = names[0];
            }
        }
    }

private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type) {
        String fileName = dir + type;
        try {
            // 根据文件中的内容得到urls, 每个url表示一个扩展    http=org.apache.dubbo.rpc.protocol.http.HttpProtocol
            Enumeration<java.net.URL> urls;
            ClassLoader classLoader = findClassLoader();
            if (classLoader != null) {
                urls = classLoader.getResources(fileName);
            } else {
                urls = ClassLoader.getSystemResources(fileName);
            }
            if (urls != null) {
                while (urls.hasMoreElements()) {
                    java.net.URL resourceURL = urls.nextElement();
                    // 遍历url进行加载,把扩展类添加到extensionClasses中
                    loadResource(extensionClasses, classLoader, resourceURL);
                }
            }
        } catch (Throwable t) {
            logger.error("Exception occurred when loading extension class (interface: " +
                    type + ", description file: " + fileName + ").", t);
        }
    }

private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
        try {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
                String line;
                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();
                                line = line.substring(i + 1).trim();
                            }
                            if (line.length() > 0) {
                                // 加载类,并添加到extensionClasses中
                                loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
                            }
                        } 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);
        }
    }

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类
        if (clazz.isAnnotationPresent(Adaptive.class)) {
            cacheAdaptiveClass(clazz);
        } else if (isWrapperClass(clazz)) {
            // 是一个Wrapper类
            cacheWrapperClass(clazz);
        } else {
            // 需要有无参的构造方法
            clazz.getConstructor();

            // 在文件中没有name,但是在类上指定了Extension的注解上指定了name
            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)) {
                // 缓存一下被Activate注解了的类
                cacheActivateClass(clazz, names[0]);

                // 有多个名字
                for (String n : names) {
                    // clazz: name
                    cacheName(clazz, n);
                    // name: clazz
                    saveInExtensionClass(extensionClasses, clazz, n);
                }
            }
        }
    }

Dubbo中的依赖注入源码解析

ExtensionLoader.injectExtension() 对前面创建出来的对象进行属性自动注入

1、通过seter方法来获取需要注入的实例名
2、从ioc中获取。 dubbo支持从 spring和spi两种方式来注入

private T injectExtension(T instance) {

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

        try {
            for (Method method : instance.getClass().getMethods()) {
                if (!isSetter(method)) {
                    continue;
                }

                // 利用set方法注入

                /**
                 * Check {@link DisableInject} to see if we need auto injection for this property
                 */
                if (method.getAnnotation(DisableInject.class) != null) {
                    continue;
                }

                // set方法中的参数类型
                Class<?> pt = method.getParameterTypes()[0];   // Person接口
                if (ReflectUtils.isPrimitives(pt)) {
                    continue;
                }

                try {
                    // 得到setXxx中的xxx
                    String property = getSetterProperty(method);   // person

                    // 根据参数类型或属性名,从objectFactory中获取到对象,然后调用set方法进行注入
                    // AdaptiveExtensionFactory
                    Object object = objectFactory.getExtension(pt, property); // User.class, user
                    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;
    }
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

    private final List<ExtensionFactory> factories;

    public AdaptiveExtensionFactory() {
        // 支持哪些ExtensionFactory (Spi, SPring)
        ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);

        List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();

        for (String name : loader.getSupportedExtensions()) { // spi, spring
            list.add(loader.getExtension(name));
        }
        factories = Collections.unmodifiableList(list);
    }

    @Override
    public <T> T getExtension(Class<T> type, String name) {
        // 遍历两个ExtensionFactory,从ExtensionFactory中得到实例,只要从某个ExtensionFactory中获取到对象实例就可以了
        for (ExtensionFactory factory : factories) {
            T extension = factory.getExtension(type, name);  // SpringExtensionFactory,, SpiExtensionFactory
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }

}
    @Override
    public <T> T getExtension(Class<T> type, String name) {
        // 遍历两个ExtensionFactory,从ExtensionFactory中得到实例,只要从某个ExtensionFactory中获取到对象实例就可以了
        for (ExtensionFactory factory : factories) {
            T extension = factory.getExtension(type, name);  // SpringExtensionFactory,, SpiExtensionFactory
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }
/**
 * SpiExtensionFactory
 */
public class SpiExtensionFactory implements ExtensionFactory {

    @Override
    public <T> T getExtension(Class<T> type, String name) {


        // 接口上存在SPI注解
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);

            if (!loader.getSupportedExtensions().isEmpty()) {
                return loader.getAdaptiveExtension(); // 接口的Adaptive类(代理对象)
            }
        }
        return null;
    }

}
/**
 * SpringExtensionFactory
 */
public class SpringExtensionFactory implements ExtensionFactory {
    private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class);

    private static final Set<ApplicationContext> CONTEXTS = new ConcurrentHashSet<ApplicationContext>();
    private static final ApplicationListener SHUTDOWN_HOOK_LISTENER = new ShutdownHookListener();

    public static void addApplicationContext(ApplicationContext context) {
        CONTEXTS.add(context);
        if (context instanceof ConfigurableApplicationContext) {
            ((ConfigurableApplicationContext) context).registerShutdownHook();
            DubboShutdownHook.getDubboShutdownHook().unregister();
        }
        BeanFactoryUtils.addApplicationListener(context, SHUTDOWN_HOOK_LISTENER);
    }

    public static void removeApplicationContext(ApplicationContext context) {
        CONTEXTS.remove(context);
    }

    public static Set<ApplicationContext> getContexts() {
        return CONTEXTS;
    }

    // currently for test purpose
    public static void clearContexts() {
        CONTEXTS.clear();
    }


    // 从Spring容器中获取bean
    // 先根据name拿,再根据类型拿
    @Override
    @SuppressWarnings("unchecked")
    public <T> T getExtension(Class<T> type, String name) {

        //SPI should be get from SpiExtensionFactory
        // 如果接口上存在SPI注解,就不从spring中获取对象实例了
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            return null;
        }

        // 从ApplicationContext中获取bean, byname
        for (ApplicationContext context : CONTEXTS) {
            if (context.containsBean(name)) {
                Object bean = context.getBean(name);
                if (type.isInstance(bean)) {
                    return (T) bean;
                }
            }
        }

        logger.warn("No spring extension (bean) named:" + name + ", try to find an extension (bean) of type " + type.getName());

        if (Object.class == type) {
            return null;
        }

        // byType
        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);
                }
            }
        }

        logger.warn("No spring extension (bean) named:" + name + ", type:" + type.getName() + " found, stop get bean.");

        return null;
    }

    private static class ShutdownHookListener implements ApplicationListener {
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            if (event instanceof ContextClosedEvent) {
                DubboShutdownHook shutdownHook = DubboShutdownHook.getDubboShutdownHook();
                shutdownHook.doDestroy();
            }
        }
    }
}

Dubbo中的AOP实现源码解析

dubbo的aop就很简单就是通过wapper接口来实现
例如上面WapperCar:
即在获取black时会把BlackCar通过构造方法传给WapperCar,然后返回WapperCar对象。
所有AOP代理逻辑都在WapperCar里面实现。

private T createExtension(String name) {
        // 获取扩展类  {name: Class}  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);

            // AOP,cachedWrapperClasses无序
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (CollectionUtils.isNotEmpty(wrapperClasses)) {
                for (Class<?> wrapperClass : wrapperClasses) {
                    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);
        }
    }

Dubbo中的Adaptive机制源码解析

@Adaptive 打在类上
@Adaptive 打在方法上

Adaptive 打在类上

ExtensionLoader 类的构造方法中有一段逻辑。ExtensionFactory的Adaptive实现类

    private ExtensionLoader(Class<?> type) {
        this.type = type;
        // objectFactory表示当前ExtensionLoader内部的一个对象工厂,可以用来获取对象  AdaptiveExtensionFactory
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

//其中AdaptiveExtensionFactory就是在类上加了@Adaptive注解
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory 

//这段代码就是会获取被@Adaptive标注的实现类
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()

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;
    }

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);
    }
}

private Class<?> getAdaptiveExtensionClass() {
        // 获取当前接口的所有扩展类
        getExtensionClasses();
        // 缓存了@Adaptive注解标记的类
        if (cachedAdaptiveClass != null) {
            return cachedAdaptiveClass;
        }
        // 如果某个接口没有手动指定一个Adaptive类,那么就自动生成一个Adaptive类
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
如果找到了@Adaptive标注的实现类,直接返回然后实例化
如果没有找到@Adaptive标注的实现类,则会通过代理生成一个类并实例化返回
private Class<?> createAdaptiveExtensionClass() {
    // cachedDefaultName表示接口默认的扩展类
    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();
    return compiler.compile(code, classLoader);
}


Adaptive 打在方法上

上面如果没有找到@Adaptive标注的类。则会去动态代理生成一个类。@Adaptive在方法上的作用就体现出来了
1、加了@Adaptive 的方法会被代理。其他的方法则默认方法体都是抛异常
2、加了@Adaptive 的方法的形参上必须有URL类型的参数或者对象有getURL的方法。可以看代理类的源代码。

 public String generate() {
        // no need to generate adaptive class since there's no adaptive method found.
        if (!hasAdaptiveMethod()) {
            throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!");
        }

        StringBuilder code = new StringBuilder();
        code.append(generatePackageInfo());
        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();
    }

    /**
     * generate method declaration
     */
    private String generateMethod(Method method) {
        String methodReturnType = method.getReturnType().getCanonicalName();
        String methodName = method.getName();
        // 生成方法体很重要
        String methodContent = generateMethodContent(method);
        String methodArgs = generateMethodArguments(method);
        String methodThrows = generateMethodThrows(method);
        return String.format(CODE_METHOD_DECLARATION, methodReturnType, methodName, methodArgs, methodThrows, methodContent);
    }

/**
     * generate method content
     */
    private String generateMethodContent(Method method) {
        // 方法上存在Adaptive注解才进行代理
        Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
        StringBuilder code = new StringBuilder(512);
        if (adaptiveAnnotation == null) {
            return generateUnsupported(method);
        } else {
            // 方法中URL类型参数的下标
            int urlTypeIndex = getUrlTypeIndex(method);

            // found parameter in URL type
            // 寻找URL
            // 1. 如果当前方法中有URl类型的参数,那么url就是该参数值
            // 2. 如果当前方法中没有URL类型的参数,但是当前方法中有某个类型中的get方法返回了URl类型,那么就调用那个get方法得到一个url对象
            if (urlTypeIndex != -1) {
                // Null Point check
                code.append(generateUrlNullCheck(urlTypeIndex));
            } else {
                // did not find parameter in URL type
                code.append(generateUrlAssignmentIndirectly(method));
            }

            // 根据这个value去找具体的扩展类
            String[] value = getMethodAdaptiveValue(adaptiveAnnotation);

            // 方法中有Invocation类型的参数
            boolean hasInvocation = hasInvocationArgument(method);

            code.append(generateInvocationArgumentNullCheck(method));


            code.append(generateExtNameAssignment(value, hasInvocation));
            // check extName == null?
            code.append(generateExtNameNullCheck(value));

            code.append(generateExtensionAssignment());

            // return statement
            code.append(generateReturnAndInvocation(method));
        }

        return code.toString();
    }

最终代理的类代码:

原接口


@SPI
public interface Car {

    @Adaptive
    String getCarName(URL url);

    String sayHell();
}

代理生成的类代码:

package com.spi;

import org.apache.dubbo.common.extension.ExtensionLoader;

public class Car$Adaptive implements com.spi.Car {
    public java.lang.String sayHell() {
        throw new UnsupportedOperationException("The method public abstract java.lang.String com.spi.Car.sayHell() of interface com.spi.Car is not adaptive method!");
    }

    public java.lang.String getCarName(org.apache.dubbo.common.URL arg0) {
        if (arg0 == null) throw new IllegalArgumentException("url == null");
        org.apache.dubbo.common.URL url = arg0;
        String extName = url.getParameter("car");
        if (extName == null)
            throw new IllegalStateException("Failed to get extension (com.spi.Car) name from url (" + url.toString() + ") use keys([car])");
        com.spi.Car extension = (com.spi.Car) ExtensionLoader.getExtensionLoader(com.spi.Car.class).getExtension(extName);
        return extension.getCarName(arg0);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七层汉堡王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值