Dubbo Wrapper

简介: 今天谈谈 Dubbo 的 org.apache.dubbo.common.bytecode.Wrapper 类Dubbo 依赖该工具在服务提供者端接收处理请求的时候、直接调用提供服务的 service 相对于传统的反射、性能其实有很大的提升

网络异常,图片无法展示
|

今天谈谈 Dubbo 的 org.apache.dubbo.common.bytecode.Wrapper 类


Dubbo 依赖该工具在服务提供者端接收处理请求的时候、直接调用提供服务的 service 相对于传统的反射、性能其实有很大的提升

private static Wrapper makeWrapper(Class<?> c) {
    String name = c.getName();
    ClassLoader cl = ClassUtils.getClassLoader(c);
    StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ ");
    StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ ");
    StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ ");
    c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
    c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
    c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
    Map<String, Class<?>> pts = new HashMap<>(); // <property name, property types>
    Map<String, Method> ms = new LinkedHashMap<>(); // <method desc, Method instance>
    List<String> mns = new ArrayList<>(); // method names.
    List<String> dmns = new ArrayList<>(); // declaring method names.
    // get all public field.
    for (Field f : c.getFields()) {
        String fn = f.getName();
        Class<?> ft = f.getType();
        if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers())) {
            continue;
        }
        c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }");
        c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }");
        pts.put(fn, ft);
    }
    Method[] methods = c.getMethods();
    // get all public method.
    boolean hasMethod = hasMethods(methods);
    if (hasMethod) {
        c3.append(" try{");
        for (Method m : methods) {
            //ignore Object's method.
            if (m.getDeclaringClass() == Object.class) {
                continue;
            }
            String mn = m.getName();
            c3.append(" if( \"").append(mn).append("\".equals( $2 ) ");
            int len = m.getParameterTypes().length;
            c3.append(" && ").append(" $3.length == ").append(len);
            boolean override = false;
            for (Method m2 : methods) {
                if (m != m2 && m.getName().equals(m2.getName())) {
                    override = true;
                    break;
                }
            }
            if (override) {
                if (len > 0) {
                    for (int l = 0; l < len; l++) {
                        c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"")
                                .append(m.getParameterTypes()[l].getName()).append("\")");
                    }
                }
            }
            c3.append(" ) { ");
            if (m.getReturnType() == Void.TYPE) {
                c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;");
            } else {
                c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");");
            }
            c3.append(" }");
            mns.add(mn);
            if (m.getDeclaringClass() == c) {
                dmns.add(mn);
            }
            ms.put(ReflectUtils.getDesc(m), m);
        }
        c3.append(" } catch(Throwable e) { ");
        c3.append("     throw new java.lang.reflect.InvocationTargetException(e); ");
        c3.append(" }");
    }
    c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }");
    // deal with get/set method.
    Matcher matcher;
    for (Map.Entry<String, Method> entry : ms.entrySet()) {
        String md = entry.getKey();
        Method method = entry.getValue();
        if ((matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
            String pn = propertyName(matcher.group(1));
            c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
            pts.put(pn, method.getReturnType());
        } else if ((matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md)).matches()) {
            String pn = propertyName(matcher.group(1));
            c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
            pts.put(pn, method.getReturnType());
        } else if ((matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
            Class<?> pt = method.getParameterTypes()[0];
            String pn = propertyName(matcher.group(1));
            c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt, "$3")).append("); return; }");
            pts.put(pn, pt);
        }
    }
    c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or setter method in class " + c.getName() + ".\"); }");
    c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or setter method in class " + c.getName() + ".\"); }");
    // make class
    long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
    ClassGenerator cc = ClassGenerator.newInstance(cl);
    cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw") + id);
    cc.setSuperClass(Wrapper.class);
    cc.addDefaultConstructor();
    cc.addField("public static String[] pns;"); // property name array.
    cc.addField("public static " + Map.class.getName() + " pts;"); // property type map.
    cc.addField("public static String[] mns;"); // all method name array.
    cc.addField("public static String[] dmns;"); // declared method name array.
    for (int i = 0, len = ms.size(); i < len; i++) {
        cc.addField("public static Class[] mts" + i + ";");
    }
    cc.addMethod("public String[] getPropertyNames(){ return pns; }");
    cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }");
    cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }");
    cc.addMethod("public String[] getMethodNames(){ return mns; }");
    cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }");
    cc.addMethod(c1.toString());
    cc.addMethod(c2.toString());
    cc.addMethod(c3.toString());
    try {
        Class<?> wc = cc.toClass();
        // setup static field.
        wc.getField("pts").set(null, pts);
        wc.getField("pns").set(null, pts.keySet().toArray(new String[0]));
        wc.getField("mns").set(null, mns.toArray(new String[0]));
        wc.getField("dmns").set(null, dmns.toArray(new String[0]));
        int ix = 0;
        for (Method m : ms.values()) {
            wc.getField("mts" + ix++).set(null, m.getParameterTypes());
        }
        return (Wrapper) wc.newInstance();
    } catch (RuntimeException e) {
        throw e;
    } catch (Throwable e) {
        throw new RuntimeException(e.getMessage(), e);
    } finally {
        cc.release();
        ms.clear();
        mns.clear();
        dmns.clear();
    }
}
复制代码


其实这段代码就是动态生成一个包装类、生成的类继承 org.apache.dubbo.common.bytecode.Wrapper


主要涉及有三个方法

  • getPropertyValue
  • invokeMethod
  • setPropertyValue

生成的类其实是

public class TestWrapper {
    private String name;
    private Integer age;
    public String address;
    public String sayHi(){
        return "hi";
    }
    public String sayGoodbye() {
        return "bye";
    }
}
复制代码


看下生成的 Wrapper 对象

package org.apache.dubbo.common.bytecode;
public class Wrapper0 extends Wrapper {
    /**
     * property name array.
     */
    public static String[] pns;
    /**
     * property type map.
     */
    public static Map pts;
    /**
     * all method name array.
     */
    public static String[] mns;
    /**
     * declared method name array.
     */
    public static String[] dmns;
    public static Class[] mts0; //存放方法的参数类型
    public static Class[] mts1; // 存放方法的参数类型
    public String[] getPropertyNames(){ return pns; }
    public boolean hasProperty(String n){ return pts.containsKey(n); }
    public Class getPropertyType(String n){ return (Class)pts.get(n); }
    public String[] getMethodNames(){ return mns; }
    public String[] getDeclaredMethodNames(){ return dmns; }
    public Object getPropertyValue(Object o, String n) {
        TestWrapper w;
        try {
            w = ((TestWrapper) $1);
        } catch (Throwable e) {
            throw new IllegalArgumentException(e);
        }
        if ($2.equals("address")) {
            return ($w) w.address;
        }
        throw new org.apache.dubbo.common.bytecode.NoSuchPropertyException("Not found property \"" + $2 + "\" field or setter method in class TestWrapper.");
    }
    public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws java.lang.reflect.InvocationTargetException {
        TestWrapper w;
        try {
            w = ((TestWrapper) $1);
        } catch (Throwable e) {
            throw new IllegalArgumentException(e);
        }
        try {
            if ("sayHi".equals($2) && $3.length == 0) {
                return ($w) w.sayHi();
            }
            if ("sayGoodbye".equals($2) && $3.length == 0) {
                return ($w) w.sayGoodbye();
            }
        } catch (Throwable e) {
            throw new java.lang.reflect.InvocationTargetException(e);
        }
        throw new org.apache.dubbo.common.bytecode.NoSuchMethodException("Not found method \"" + $2 + "\" in class TestWrapper.");
    }
    public void setPropertyValue(Object o, String n, Object v) {
        TestWrapper w;
        try {
            w = ((TestWrapper) $1);
        } catch (Throwable e) {
            throw new IllegalArgumentException(e);
        }
        if ($2.equals("address")) {
            w.address = (java.lang.String) $3;
            return;
        }
        throw new org.apache.dubbo.common.bytecode.NoSuchPropertyException("Not found property \"" + $2 + "\" field or setter method in class TestWrapper.");
    }
}
复制代码
  • getPropertyValue 能获取到的都是申明为 public 的属性
  • invokeMethod 能获取到的都是申明为 public 的方法
  • setPropertyValue 能获取到的都是申明为 public 的属性


原因简单啊、因为不在同一个包下、生成的这个 Wrapper 类是跟 org.apache.dubbo.common.bytecode.Wrapper 在同一个包中

至于他生成的几个静态变量

网络异常,图片无法展示
|


其实都是为了以后方便获取被包装类的相关信息、比如在 ServiceConfig 的 doExportUrlsFor1Protocol 方法的时候

网络异常,图片无法展示
|


就通过生成一个 Wrapper 获取服务接口暴露出去多少个方法、获取起方法名、放到 map 里面、为后续生成注册的 url 做准备

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
运维 Dubbo 中间件
Dubbo3 源码解读-宋小生-6:Dubbo的SPI扩展机制之普通扩展对象的创建与Wrapper机制的源码解析
> Dubbo3 已经全面取代 HSF2 成为阿里的下一代服务框架,2022 双十一基于 Dubbo3 首次实现了关键业务不停推、不降级的全面用户体验提升,从技术上,大幅提高研发与运维效率的同时地址推送等关键资源利用率提升超 40%,基于三位一体的开源中间件体系打造了阿里在云上的单元化最佳实践和统一标准,同时将规模化实践经验与技术创新贡献开源社区,极大的推动了开源技术与标准的发展。 > 本文是
197 0
|
4月前
|
Dubbo Java 应用服务中间件
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
|
10月前
|
负载均衡 Dubbo 应用服务中间件
微服务技术系列教程(31) - Dubbo-原理及负载均衡分析
微服务技术系列教程(31) - Dubbo-原理及负载均衡分析
84 0
|
10月前
|
Dubbo Java 应用服务中间件
阿里新框架干掉微服务,换下Dubbo,Spring CloudAlibaba王者降临
tm快了,不知不觉中金九银十的秋招已经快结束了,不少同学现在已经拿到offer了吧~现在的面试可是越来越难了,动不动就是“互联网三高”。
阿里新框架干掉微服务,换下Dubbo,Spring CloudAlibaba王者降临
|
10月前
|
Dubbo Java 应用服务中间件
微服务技术系列教程(30) - Dubbo-SpringCloud与Dubbo区别
微服务技术系列教程(30) - Dubbo-SpringCloud与Dubbo区别
68 0
|
22天前
|
Dubbo Java 应用服务中间件
💥Spring Cloud Dubbo火爆来袭!微服务通信的终极利器,你知道它有多强大吗?🔥
【8月更文挑战第29天】随着信息技术的发展,微服务架构成为企业应用开发的主流模式,而高效的微服务通信至关重要。Spring Cloud Dubbo通过整合Dubbo与Spring Cloud的优势,提供高性能RPC通信及丰富的生态支持,包括服务注册与发现、负载均衡和容错机制等,简化了服务调用管理并支持多种通信协议,提升了系统的可伸缩性和稳定性,成为微服务通信领域的优选方案。开发者仅需关注业务逻辑,而无需过多关心底层通信细节,使得Spring Cloud Dubbo在未来微服务开发中将更加受到青睐。
45 0
|
1月前
|
负载均衡 Dubbo 应用服务中间件
框架巨擘:Dubbo如何一统异构微服务江湖,成为开发者的超级武器!
【8月更文挑战第8天】在软件开发中,微服务架构因灵活性和可扩展性备受欢迎。面对异构微服务的挑战,Apache Dubbo作为高性能Java RPC框架脱颖而出。它具备服务注册与发现、负载均衡及容错机制等核心特性,支持多种通信协议和序列化方式,能有效连接不同技术栈的微服务。Dubbo的插件化设计保证了面向未来的扩展性,使其成为构建稳定高效分布式系统的理想选择。
35 5
|
4月前
|
Dubbo Java 应用服务中间件
阿里巴巴资深架构师深度解析微服务架构设计之SpringCloud+Dubbo
软件架构是一个包含各种组织的系统组织,这些组件包括Web服务器,应用服务器,数据库,存储,通讯层),它们彼此或和环境存在关系。系统架构的目标是解决利益相关者的关注点。
|
4月前
|
Dubbo Cloud Native 应用服务中间件
【阿里云云原生专栏】云原生环境下的微服务治理:阿里云 Dubbo 与 Nacos 的深度整合
【5月更文挑战第25天】阿里云Dubbo和Nacos提供微服务治理的强大工具,整合后实现灵活高效的治理。Dubbo是高性能RPC框架,Nacos则负责服务发现和配置管理。整合示例显示,通过Nacos注册中心,服务能便捷注册发现,动态管理配置。简化部署,提升适应性,但也需注意服务稳定性和策略规划。这种整合为云原生环境的微服务架构带来强大支持,未来应用前景广阔。
262 2
|
4月前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo: 微服务通信的高效解决方案
【4月更文挑战第28天】在微服务架构的发展中,服务间的高效通信至关重要。Spring Cloud Dubbo 提供了一种基于 RPC 的通信方式,使得服务间的调用就像本地方法调用一样简单。本篇博客将探讨 Spring Cloud Dubbo 的核心概念,并通过具体实例展示其在项目中的实战应用。
97 2