【问题标题】:How to read value of java annotation with JDK8 and JDK11?如何用JDK8和JDK11读取java注解的值?
【发布时间】:2020-03-12 10:01:49
【问题描述】:

JDK8和JDK11如何读取java注解的值?

import io.cucumber.java.en.When;

public class Sof {

    private static final Logger log = LoggerFactory.getLogger(Sof.class);

    @When(value = "I update text {string} with {string}(\\?)")
    public static void main(String[] args) {
        Class c = Sof.class;
        Method[] methods = c.getMethods();
        Method method = null;
        for (Method m : methods) {
            if (m.getName().equals("main")) {
                method = m;
            }
        }
        Annotation stepAnnotation = method.getAnnotation(When.class);
        Object as[] = { "a", "b" };
        Matcher matcher = Pattern.compile("value=(.*)\\)").matcher(stepAnnotation.toString());
        if (matcher.find()) {
            log.info("---> " + stepAnnotation.annotationType().getSimpleName() + " " + String.format(matcher.group(1).replaceAll("\\{\\S+\\}", "{%s}").replace("(\\?)", ""), as));
        } else {
            System.err.println("error");
        }
    }

}

/!\ 实际上,我不知道注解@When 的类型。这可以是 io.cucumber.java 包中的任何接口

结果 JDK8:

---> When I update text {a} with {b}

结果 JDK11(额外引用):stepAnnotation.toString() 不同!)

---> When "I update text {a} with {b}"

编辑 openjdk11oraclejdk11 不尊重 javadoc:

/**
 * Returns a string representation of this annotation.  The details
 * of the representation are implementation-dependent, but the following
 * may be regarded as typical:
 * <pre>
 *   &#064;com.acme.util.Name(first=Alfred, middle=E., last=Neuman)
 * </pre>
 *
 * @return a string representation of this annotation
 */
String toString();

【问题讨论】:

    标签: java openjdk-11 openjdk-8


    【解决方案1】:

    您不应依赖通常仅用于调试/记录的toString() 实现。

    有关如何读取注释值的更多详细信息,请参阅Is it possible to read the value of a annotation in java?

    更新:

    要通过反射来做所有事情,你可以这样:

    import org.springframework.transaction.annotation.Transactional;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.util.Arrays;
    
    public class AnnotationTest {
        public static void main(String[] args) throws IllegalAccessException, InvocationTargetException {
            Method[] methods = AnnotationTest.class.getMethods();
            System.out.println("methods = " + Arrays.toString(methods));
            for (Method method : methods) {
                System.out.println("method = " + method);
                Annotation[] annotations = method.getAnnotations();
                System.out.println("annotations = " + Arrays.toString(annotations));
    
                for (Annotation annotation : annotations) {
                    System.out.println("annotation = " + annotation);
    
                    Class<? extends Annotation> annotationClass = annotation.annotationType();
                    System.out.println("annotationClass = " + annotationClass);
                    Method[] annotationMethods = annotationClass.getMethods();
                    System.out.println("annotation methods = " + Arrays.toString(annotationMethods));
                    for (Method annotationMethod : annotationMethods) {
                        if (Modifier.isPublic(annotationMethod.getModifiers())) {
                            String name = annotationMethod.getName();
                            Object o = annotationMethod.invoke(annotation);
                            System.out.println(name + ": " + o);
                        }
    
                    }
                }
            }
        }
    
        @Transactional("bla")
        public void test() {
        }
    }
    

    (我在这里使用了 Spring 的注释之一,因为这是我的类路径中碰巧有的)

    更新(解决方案结束):

    @When(value = "I update text {string} with {string}(\\?)")
    public static void main(String[] args) {
        Object as[] = { "a", "b" };
        Class c = Sof.class;
        Method[] methods = c.getMethods();
        Method method = null;
        for (Method m : methods) {
            if (m.getName().equals("main")) {
                method = m;
            }
        }
        Annotation stepAnnotation = method.getAnnotation(When.class);
        Class<? extends Annotation> annotationClass = stepAnnotation.annotationType();
        try {
            Method valueMethods = annotationClass.getDeclaredMethod("value");
            if (Modifier.isPublic(valueMethods.getModifiers())) {
                log.info("---> {} " + String.format(valueMethods.invoke(stepAnnotation).toString().replaceAll("\\{\\S+\\}", "{%s}").replace("(\\?)", ""), as),
                        stepAnnotation.annotationType().getSimpleName());
            }
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
            e1.printStackTrace();
        }
    }
    

    【讨论】:

    • 您的链接很好,但实际上,我不知道 @When 注释的类型。这可以是io.cucumber.java 包中的任何接口
    • @sgrillon 然后获取所有注解并遍历它们
    • @sgrillon 我添加了一个如何通过反射获取注释值的示例。
    猜你喜欢
    • 1970-01-01
    • 2020-03-26
    • 2019-06-24
    • 2021-10-25
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多