Dubbo原始碼解讀:appendAnnotation [01]

FrankYou發表於2018-07-24

 

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

 

相關文章