Невозможно прочитать аннотации из .class - PullRequest
2 голосов
/ 21 апреля 2020

Я хочу читать аннотации на уровне класса, используя ядро ​​java. Я пробовал это:

Аннотация:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Fix {

    public String[] author() default "";
}

Класс:

@Fix(author="John Doe")
public class TestClass {

    public void test(){

    }
}

Тестовый метод для чтения класса:

ResourcePatternResolver resolversec = new PathMatchingResourcePatternResolver();
            Resource[] resour = resolversec.getResources("classpath*:/com/validation/*.class");
            Class<?> cl = resolversec.getClassLoader().loadClass("com.validation.ValidateCharacteristicsProcessor");

            if(cl != null){
                out.println("Class is not null " + cl.getSimpleName());
            }

            Fix fix = cl.getAnnotation(Fix.class);
            if (fix != null) {
                out.println("!!!! " + fix.author());
            }

Но аннотация @Fix становится пустой. Знаете ли вы, как правильно читать эту аннотацию?

Заполните пример: https://pastebin.com/KbBAZVfB

Ответы [ 4 ]

4 голосов
/ 02 мая 2020

Прежде всего, я не думаю, что com.validation.ValidateCharacteristicsProcessor существует в вашем проекте. Тем не менее, если вы пытаетесь загрузить этот класс (если он есть), проверьте, аннотирован ли этот класс @Fix или нет.


Я показываю с предоставленным вами TestClass.

Я попробовал простой подход.

Сначала я создал простой проект maven для моего удобства.

Структура проекта:

enter image description here

Fix. java

package com.example;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(TYPE)
public @interface Fix {

    public String[] author() default "";

}

TestClass. java

package com.example;

@Fix(author = "John Doe")
public class TestClass {

    public void test() {

    }

}

Main. java

package com.example;

    public class Main {

        public static void main(String[] args) throws ClassNotFoundException {

            // create an instance of TestClass
            TestClass t = new TestClass();

            // use reflection to extract annotation from TestClass.class 
            Fix fix = t.getClass().getAnnotation(Fix.class); // or TestClass.class.getAnnotation(Fix.class);


            // print the value   
            System.out.println(fix.author()[0]);

        }

    }

Вывод:

enter image description here

Примечание: Если вы хотите прочитать все классы из пакета.

Этот вопрос имеет четко определенный ответ - Можете ли вы найти все классы в пакете, используя отражение?

Я узнал отражение из этой статьи. -> http://tutorials.jenkov.com/java-reflection/index.html

Это очень хороший блог.


Если вы хотите продолжить с кодом, который вы предоставили, то у меня есть исправление приведено ниже.

Я исследовал ResourcePatternResolver и думаю, что вы используете spring-core для чтения классов.

Итак, я обновил ваш код.

package com.example;


import java.io.IOException;

import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

public class Main {

    public static void main(String[] args) throws ClassNotFoundException {

        ResourcePatternResolver resolversec = new PathMatchingResourcePatternResolver();
        Class<?> cl = resolversec.getClassLoader().loadClass("com.example.TestClass");

        if (cl != null) {
            System.out.println("Class is not null " + cl.getSimpleName());
        }

        Fix fix = cl.getAnnotation(Fix.class);
        if (fix != null) {
            System.out.println("!!!! " + fix.author()[0]);
        }

    }

}

Вывод:

enter image description here

Обновлено pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>read-annotations</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
4 голосов
/ 01 мая 2020

Вы звоните getAnnotation(Fix.class) на com.validation.ValidateCharacteristicsProcessor, а не на TestClass. Аннотация, как и ожидалось, присутствует на TestClass:

jshell> TestClass.class.getAnnotations()
$4 ==> Annotation[1] { @Fix(author={"John Doe"}) }

jshell> TestClass.class.getAnnotation(Fix.class)
$5 ==> @Fix(author={"John Doe"})

jshell> TestClass.class.getAnnotation(Fix.class).author()[0]
$6 ==> "John Doe"

Если посмотреть на ваш полный пример, я бы предположил, что либо predictedName не является правильной строкой, либо проверяемый вами класс на самом деле не аннотированы должным образом.

Скорее всего, это поможет создать небольшой MCVE желаемого поведения и затем включить его обратно в ваш более крупный проект, когда у вас будет работать базовый c подход.

0 голосов
/ 03 мая 2020

Вы загружаете неверный класс в своем коде. Вы должны загрузить TestClass, так как аннотация Fix находится на TestClass, а не на классе ValidateCharacteristicsProcessor

0 голосов
/ 01 мая 2020

Итерация класса с собственным java или с библиотекой в ​​пакете, смотрите эту ссылку: Можете ли вы найти все классы в пакете, используя отражение?

После того, как он итерируется и показывается с этим кодом :

    Arrays.stream(getClasses("package.name.asdf")).forEach(aClass -> {
        Fix annotation = (Fix) aClass.getAnnotation(Fix.class);
        if (annotation != null) System.out.println(Arrays.asList(annotation.author()));
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...