zoukankan      html  css  js  c++  java
  • Dubbo源码解读:appendAnnotation [01]

    import java.lang.reflect.Method;
    
    public class AppendAnnotation {
        /**
         * 获取某个Annotation实例的所有方法值(实际是Annotation的属性值),并把这些方法的值赋值给调用此方法的类的相关的setter方法。
         */
        protected void appendAnnotation(Class<?> annotationClass, Object annotation) {
            Method[] methods = annotationClass.getMethods(); // 从当前类或接口中(包括父类或父接口)获取公开(public)的方法
            for (Method method : methods) {
                if (method.getDeclaringClass() != Object.class // 方法所在类不是Object本身
                        && method.getReturnType() != void.class // 方法的返回类型不是void
                        && method.getParameterTypes().length == 0 // 方法的参数个数为0
                        && Modifier.isPublic(method.getModifiers()) // 方法的修饰符为public
                        && !Modifier.isStatic(method.getModifiers())) // 方法不是静态的
                {
                    try {
                        String property = method.getName(); // 方法名称
    
                        // 如果方法的名称为“interfaceClass”或者interfaceName”,则统一把方法名称:property的值设置为“interface”
                        if ("interfaceClass".equals(property) || "interfaceName".equals(property)) {
                            property = "interface";
                        }
    
                        // 构造set方法的完整名称,比如:set+V+ersion=setVersion、set+G+roup=setGroup等等
                        String setter = "set" + property.substring(0, 1).toUpperCase() + property.substring(1);
    
                        // 通过反射的方式来调用底层方法,annotaion为被调用方法所在的对象(这里是Annotaion对象),value为方法返回值,实际上就是我们设置的annotaion的属性值。
                        Object value = method.invoke(annotation);
    
                        // 如果属性值不为null并且不是方法返回值的默认值
                        if (value != null && !value.equals(method.getDefaultValue())) {
    
                            // 把方法返回值的类型进行装箱
                            Class<?> parameterType = ReflectUtils.getBoxedClass(method.getReturnType());
    
                            // 如果方法名称(属性名称)为filter或listner,annotation中filter和listner定义的是string[]类型
                            if ("filter".equals(property) || "listener".equals(property)) {
                                parameterType = String.class;
                                value = StringUtils.join((String[]) value, ",");
                            } else if ("parameters".equals(property)) { // String[] parameters() default
                                                                        // {};这种情况下把string[]转换为Map
                                parameterType = Map.class;
                                value = CollectionUtils.toStringMap((String[]) value);
                            }
                            try {
                                // 获取AppendAnnotation方法所在类的setter名称所对应的方法(比如:ReferenceConfig类型的setConnections方法,参数值类型为:Integer)
                                Method setterMethod = getClass().getMethod(setter, parameterType);
    
                                // 通过反射的方式来调用setter方法(相当于new ReferenceConfig().setConnections(1)这样)
                                setterMethod.invoke(this, value);
                            } catch (NoSuchMethodException e) {
                                // ignore
                            }
                        }
                    } catch (Throwable e) {
                        logger.error(e.getMessage(), e);
                    }
                }
            }
        }
    }
  • 相关阅读:
    C# 协变 逆变
    go slice 理解
    为什么避免使用Task.Wait或者Task.Result
    IL笔记
    docker随笔
    领域事件
    总结笔记
    基于ASP.NET Core 3.x的端点路由(Endpoint Routing)实现控制器(Controller)和操作(Action)分离的接口服务
    CentOS7 多IP搭建SOCKS5代理服务器
    Springboot 实现数据库备份还原
  • 原文地址:https://www.cnblogs.com/frankyou/p/9359190.html
Copyright © 2011-2022 走看看