简体   繁体   English

是否可以在 java 中读取注释的值?

[英]Is it possible to read the value of a annotation in java?

this is my code:这是我的代码:

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

is it possible to read the value of my annotation @Column( columnName ="xyz123") in another class?是否可以在另一个类中读取我的注释 @Column( columnName ="xyz123") 的值?

Yes, if your Column annotation has the runtime retention是的,如果您的 Column 注释具有运行时保留

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

you can do something like this你可以做这样的事情

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

UPDATE : To get private fields use更新:要使用私有字段

Myclass.class.getDeclaredFields()

Of course it is.当然是这样。 Here is a sample annotation:这是一个示例注释:

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

    String testText();
}

And a sample annotated method:和一个示例注释方法:

class TestClass {

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

And a sample method in another class that prints the value of the testText:另一个类中的示例方法打印 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());
    }
}

Not much different for field annotations like yours.像您这样的字段注释没有太大不同。

Cheerz!干杯!

I've never done it, but it looks like Reflection provides this.我从来没有做过,但看起来Reflection提供了这个。 Field is an AnnotatedElement and so it has getAnnotation . Field是一个AnnotatedElement ,所以它有getAnnotation This page has an example (copied below); 这个页面有一个例子(复制如下); quite straightforward if you know the class of the annotation and if the annotation policy retains the annotation at runtime.如果您知道注释的类并且注释策略在运行时保留注释,则非常简单。 Naturally if the retention policy doesn't keep the annotation at runtime, you won't be able to query it at runtime.自然地,如果保留策略在运行时不保留注释,您将无法在运行时查询它。

An answer that's since been deleted (?) provided a useful link to an annotations tutorial that you may find helpful;此后已删除的答案 (?) 提供了指向注释教程的有用链接,您可能会发现它很有帮助; I've copied the link here so people can use it.我已将链接复制到此处,以便人们可以使用它。

Example from this page : 此页面的示例:

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

Elaborating to the answer of @Cephalopod, if you wanted all column names in a list you could use this oneliner:详细说明@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, eg虽然到目前为止给出的所有答案都是完全有效的,但还应该记住谷歌反射库,以获得更通用和更简单的注释扫描方法,例如

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

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

In common case you have private access for fields, so you CAN'T use getFields in reflection.通常情况下,您对字段具有私有访问权限,因此您不能在反射中使用getFields Instead of this you should use getDeclaredFields而不是这个,你应该使用getDeclaredFields

So, firstly, you should be aware if your Column annotation has the runtime retention:因此,首先,您应该知道您的 Column 注释是否具有运行时保留:

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

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(...)();请记住,这不会 100% 等价于 SomeClass.class.get(...)();

But can do the trick...但可以做的伎俩...

For the few people asking for a generic method, this should help you (5 years later :p).对于少数要求通用方法的人,这应该对您有所帮助(5 年后:p)。

For my below example, I'm pulling the RequestMapping URL value from methods that have the RequestMapping annotation.对于下面的示例,我从具有 RequestMapping 注释的方法中提取 RequestMapping URL 值。 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.并为您要阅读的任何注释交换RequestMapping 的使用。 But make sure that the annotation has @Retention(RetentionPolicy.RUNTIME) .但请确保注释具有@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 "";
}

one of the ways I used it :我使用它的方法之一:

protected List<Field> getFieldsWithJsonView(Class sourceClass, Class jsonViewName){
    List<Field> fields = new ArrayList<>();
    for (Field field : sourceClass.getDeclaredFields()) {
        JsonView jsonViewAnnotation = field.getDeclaredAnnotation(JsonView.class);
        if(jsonViewAnnotation!=null){
            boolean jsonViewPresent = false;
            Class[] viewNames = jsonViewAnnotation.value();
            if(jsonViewName!=null && Arrays.asList(viewNames).contains(jsonViewName) ){
                fields.add(field);
            }
        }
    }
    return fields;
}    

To read the value of annotation in java try to follow the following steps:要在 java 中读取注释的值,请尝试按照以下步骤操作:

  1. Create an annotation.创建注释。
  2. Follow the logic in the target class below.遵循下面目标类中的逻辑。
  3. Access the value as in Output.访问输出中的值。

Annotation注解

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

@Target({ElementType.TYPE}) // make annotation usable only for classes
@Retention(RetentionPolicy.RUNTIME) // make annotation available at the runTime
public @interface EntryPoint {
    String url();
}

Target目标

// just remember to import your annotation in this case "EntryPoint"

import java.lang.annotation.Annotation;

@EntryPoint(url = "api/v1/demo")
public class Demo {
    // get class of this.
    private final Class<? extends Demo> demo = this.getClass();
    // get specific annotation (EntryPoint.class)
    private final Annotation annotation = demo.getAnnotation(EntryPoint.class);
    // instantiate annotation and assign it value from the class annotation.
    final EntryPoint entryPoint = (EntryPoint) annotation;
}

Output输出

public class Main {
    public static void main(String[] args) {
        // create an object of the class with the annotation.
        Demo demo = new Demo();
        System.out.println(demo.entryPoint.url());
    }
}

The result is "api/v1/demo"结果是“api/v1/demo”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM