Dubbo-Adaptive实现解析

33 篇文章 0 订阅

Dubbo-Adaptive实现解析介
daptive的主要功能是对所有的扩展点进行封装为一个类,通过URL传入参数的时动态选择需要使用的
扩展点。其底层的实现原理就是动态代理

ExtensionLoader-getAdaptiveExtension


    public T getAdaptiveExtension() {
        //从缓存中获取 进行Holder和加锁的方式来保证只会被创建一次
        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 {
                        //创建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


    /**
     * 创建xxxAdaptive注解类的扩展
     * @return
     */
    @SuppressWarnings("unchecked")
    private T createAdaptiveExtension() {
        try {
            //自动依赖注入injectExtension
           // 这里使用`getAdaptiveExtensionClass`方法进行构建类并且执行实例化
            // 然后和普通的其他class相同,依旧使用injectExtension进行扩展
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
            throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
    }
injectExtension

    private T injectExtension(T instance) {
        //检测objectFactory字段
        if (objectFactory == null) {
            return instance;
        }

        try {
            //遍历其中的所有方法
            for (Method method : instance.getClass().getMethods()) {
                //方法遍历判断是否为setter方法  如果不是,忽略该方法继续下一个方法
                if (!isSetter(method)) {
                // 是否是set方法
                // 1. 以"set"开头
                // 2. 参数长度为1
                // 3. 是公开的方法
                    continue;
                }
                /**
                 * Check {@link DisableInject} to see if we need auto injection for this property
                 */
                if (method.getAnnotation(DisableInject.class) != null) {
                    //判断是否禁止注入 如果方法上明确标注了@DisableInject注解,忽略该方法
                    continue;
                }
                //根据setter方法的参数,确定扩展接口
                Class<?> pt = method.getParameterTypes()[0];
                //判断是否为基本类型 原始类型(boolean、char、byte、short、int、long、float、double)
                //如果参数为简单类型,忽略该setter方法(略)
                if (ReflectUtils.isPrimitives(pt)) {
                    continue;
                }

                try {
                    //setter方法注入 获取需要set的扩展点名称
                    String property = getSetterProperty(method);
                    //从扩展中获取对象 加载并实例化扩展实现类
                    Object object = objectFactory.getExtension(pt, property);
                    //从ExtensionLoader中加载指定的扩展点
                     比如有一个方法为setRandom(LoadBalance loadBalance),那么则以为着需要加载负载均衡中名为random的扩展点
                    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;
    }

getAdaptiveExtensionClass


  private Class<?> getAdaptiveExtensionClass() {
        //确保已经加载了所有的扩展类信息
        getExtensionClasses();
        if (cachedAdaptiveClass != null) {
            //如果已经加载过了,则直接返回
            return cachedAdaptiveClass;
        }
        //否则进行构建操作
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }

获取所有的扩展类信息

    private Map<String, Class<?>> getExtensionClasses() {
        //从缓存中获取 ExtensionLoader 加载的扩展名与扩展实现类之间的映射关系。cachedNames 集合的反向关系缓存
        Map<String, Class<?>> classes = cachedClasses.get();
        if (classes == null) {
            synchronized (cachedClasses) {
                classes = cachedClasses.get();
                if (classes == null) {
                    //加载配置文件
                    classes = loadExtensionClasses();
                    cachedClasses.set(classes);
                }
            }
        }
        return classes;
    }

createAdaptiveExtensionClass

    /**
     * 生成一个 xxxx$Adaptive 适配器类
     * @return
     */
    private Class<?> createAdaptiveExtensionClass() {
        //实例化一个新的Adaptive的代码生成器,并且进行代码生成
        String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
        //获取当前类的类加载器
        ClassLoader classLoader = findClassLoader();
        //通过扩展点,寻找编译器, 目前有Java自带的编译器和Javassist的编译器
        org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
        //编译并且生成class
        return compiler.compile(code, classLoader);
    }

具体通过 AdaptiveClassLoaderCodeGenerator.generate 方法来进行实现真正的代码生成


    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();
        //生成包的信息
        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();
    }

generateMethod

 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);
        //格式化为一个字符串
        // public %s %s(%s) %s {
        // %s
        // }
        return String.format(CODE_METHOD_DECLARATION, methodReturnType, methodName, methodArgs, methodThrows, methodContent);
    }

generateMethodContent


   private String generateMethodContent(Method method) {
        //获取Adaptive注解,只支持含有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不为空的代码
            if (urlTypeIndex != -1) {
                // Null Point check
                code.append(generateUrlNullCheck(urlTypeIndex));
            } else {
                // did not find parameter in URL type
                //获取这个方法中的所有参数列表
                // 寻找每个参数中是否有"get"开头的方法,并且返回值是URL的
                // 如果有则同样认定为找到,否则抛出异常
                code.append(generateUrlAssignmentIndirectly(method));
            }

            //获取扩展点的适配名称
            String[] value = getMethodAdaptiveValue(adaptiveAnnotation);
            // 判断是否有参数是Invocation类
            // 这里判断的主要目的在于,拥有Invocation时,则获取扩展名称的方式发生改变
            // 存在Invocation时,通过getMethodParameter,否则通过getParameter来执行
            // getMethodParameter是dubboURL中特有的,用于将"test.a"转换为"testA"的形式
            boolean hasInvocation = hasInvocationArgument(method);
            //增加有Invocation类时的不为空判断
            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();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dubbo-Admin 是 Dubbo 提供的一个可视化管理平台,用于监控和管理 Dubbo 服务。安装和部署 Dubbo-Admin 需要以下步骤: 1. 下载 Dubbo-Admin 的安装包,可以从 Dubbo 的官方 GitHub 仓库中获取。你可以访问 https://github.com/apache/dubbo-admin/releases 下载最新版本的安装包。 2. 解压下载的安装包到你选择的目录。你可以使用以下命令解压: ```shell unzip dubbo-admin-x.x.x.zip ``` 3. 进入解压后的目录,找到 `dubbo-admin-server` 目录。 4. 打开 `dubbo-admin-server` 目录下的 `src/main/resources/application.properties` 文件,修改其中的配置信息。 - 配置 Dubbo 注册中心的地址:`dubbo.registry.address=zookeeper://localhost:2181`,根据你实际的注册中心地址进行修改。 - 配置 Dubbo Admin 的访问端口:`server.port=8080`,根据你的需求进行修改。 5. 保存并关闭 `application.properties` 文件。 6. 在 `dubbo-admin-server` 目录下执行以下命令来构建 Dubbo-Admin: ```shell mvn clean package ``` 7. 构建完成后,进入 `target` 目录,执行以下命令来启动 Dubbo-Admin: ```shell java -jar dubbo-admin-x.x.x.jar ``` 8. 等待启动完成,访问 http://localhost:8080 即可进入 Dubbo-Admin 的管理界面。 请注意,安装和部署 Dubbo-Admin 需要满足以下依赖条件: - JDK 1.8 或以上版本 - Maven 3.x - ZooKeeper 3.x 或以上版本 希望以上步骤对你有帮助!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值