Programing

Java에서 주석 값을 읽을 수 있습니까?

lottogame 2020. 9. 2. 20:19
반응형

Java에서 주석 값을 읽을 수 있습니까?


이것은 내 코드입니다.

@Column(columnName="firstname")


private String firstName;

 @Column(columnName="lastname")
 private String lastName;

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

내 주석 @Column ( columnName = "xyz123")의 값을 다른 클래스에서 읽을 수 있습니까?


예, 열 주석에 런타임 보존이있는 경우

@Retention(RetentionPolicy.RUNTIME)
@interface Column {
    ....
}

당신은 이렇게 할 수 있습니다

for (Field f: MyClass.class.getFields()) {
   Column column = f.getAnnotation(Column.class);
   if (column != null)
       System.out.println(column.columnName());
}

업데이트 : 개인 필드를 사용하려면

Myclass.class.getDeclaredFields()

당연하지. 다음은 샘플 주석입니다.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {

    String testText();
}

그리고 주석이 추가 된 샘플 방법 :

class TestClass {

    @TestAnnotation(testText="zyx")
    public void doSomething() {}
}

그리고 testText의 값을 인쇄하는 다른 클래스의 샘플 메서드 :

Method[] methods = TestClass.class.getMethods();
for (Method m : methods) {
    if (m.isAnnotationPresent(TestAnnotation.class)) {
        TestAnnotation ta = m.getAnnotation(TestAnnotation.class);
        System.out.println(ta.testText());
    }
}

귀하와 같은 필드 주석의 경우 크게 다르지 않습니다.

치어 즈!


나는 그것을 한 적이 없지만 Reflection 이 이것을 제공 하는 것처럼 보입니다 . Field입니다 AnnotatedElement그리고 그것은있다 getAnnotation. 이 페이지 에는 예제가 있습니다 (아래 복사). 주석의 클래스를 알고 있고 주석 정책이 런타임에 주석을 유지한다면 매우 간단합니다. 당연히 보존 정책이 주석을 런타임에 유지하지 않으면 런타임에 쿼리 할 수 ​​없습니다.

이후 삭제 된 답변 (?)은 유용한 주석 자습서에 대한 유용한 링크를 제공했습니다 . 사람들이 사용할 수 있도록 여기에 링크를 복사했습니다.

이 페이지의:

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {
  String str();

  int val();
}

class Meta {
  @MyAnno(str = "Two Parameters", val = 19)
  public static void myMeth(String str, int i) {
    Meta ob = new Meta();

    try {
      Class c = ob.getClass();

      Method m = c.getMethod("myMeth", String.class, int.class);

      MyAnno anno = m.getAnnotation(MyAnno.class);

      System.out.println(anno.str() + " " + anno.val());
    } catch (NoSuchMethodException exc) {
      System.out.println("Method Not Found.");
    }
  }

  public static void main(String args[]) {
    myMeth("test", 10);
  }
}

@Cephalopod의 대답에 대해 자세히 설명하면 목록에있는 모든 열 이름을 원하면이 oneliner를 사용할 수 있습니다.

List<String> columns = 
        Arrays.asList(MyClass.class.getFields())
              .stream()
              .filter(f -> f.getAnnotation(Column.class)!=null)
              .map(f -> f.getAnnotation(Column.class).columnName())
              .collect(Collectors.toList());

While all the answers given so far are perfectly valid, one should also keep in mind the google reflections library for a more generic and easy approach to annotation scanning, e.g.

 Reflections reflections = new Reflections("my.project.prefix");

 Set<Field> ids = reflections.getFieldsAnnotatedWith(javax.persistence.Id.class);

You can also use generic types, in my case, taking into account everything said before you can do something like:

public class SomeTypeManager<T> {

    public SomeTypeManager(T someGeneric) {

        //That's how you can achieve all previously said, with generic types.
        Annotation[] an = someGeneric.getClass().getAnnotations();

    }

}

Remember, that this will not equival at 100% to SomeClass.class.get(...)();

But can do the trick...


In common case you have private access for fields, so you CAN'T use getFields in reflection. Instead of this you should use getDeclaredFields

So, firstly, you should be aware if your Column annotation has the runtime retention:

@Retention(RetentionPolicy.RUNTIME)
@interface Column {
}

After that you can do something like this:

for (Field f: MyClass.class.getDeclaredFields()) {
   Column column = f.getAnnotation(Column.class);
       // ...
}

Obviously, you would like to do something with field - set new value using annotation value:

Column annotation = f.getAnnotation(Column.class);
if (annotation != null) {
    new PropertyDescriptor(f.getName(), Column.class).getWriteMethod().invoke(
        object,
        myCoolProcessing(
            annotation.value()
        )
    );
}

So, full code can be looked like this:

for (Field f : MyClass.class.getDeclaredFields()) {
    Column annotation = f.getAnnotation(Column.class);
    if (annotation != null)
        new PropertyDescriptor(f.getName(), Column.class).getWriteMethod().invoke(
                object,
                myCoolProcessing(
                        annotation.value()
                )
        );
}

For the few people asking for a generic method, this should help you (5 years later :p).

For my below example, I'm pulling the RequestMapping URL value from methods that have the RequestMapping annotation. To adapt this for fields, just change the

for (Method method: clazz.getMethods())

to

for (Field field: clazz.getFields())

And swap usage of RequestMapping for whatever annotation you are looking to read. But make sure that the annotation has @Retention(RetentionPolicy.RUNTIME).

public static String getRequestMappingUrl(final Class<?> clazz, final String methodName)
{
    // Only continue if the method name is not empty.
    if ((methodName != null) && (methodName.trim().length() > 0))
    {
        RequestMapping tmpRequestMapping;
        String[] tmpValues;

        // Loop over all methods in the class.
        for (Method method: clazz.getMethods())
        {
            // If the current method name matches the expected method name, then keep going.
            if (methodName.equalsIgnoreCase(method.getName()))
            {
                // Try to extract the RequestMapping annotation from the current method.
                tmpRequestMapping = method.getAnnotation(RequestMapping.class);

                // Only continue if the current method has the RequestMapping annotation.
                if (tmpRequestMapping != null)
                {
                    // Extract the values from the RequestMapping annotation.
                    tmpValues = tmpRequestMapping.value();

                    // Only continue if there are values.
                    if ((tmpValues != null) && (tmpValues.length > 0))
                    {
                        // Return the 1st value.
                        return tmpValues[0];
                    }
                }
            }
        }
    }

    // Since no value was returned, log it and return an empty string.
    logger.error("Failed to find RequestMapping annotation value for method: " + methodName);

    return "";
}

참고URL : https://stackoverflow.com/questions/4296910/is-it-possible-to-read-the-value-of-a-annotation-in-java

반응형