Java的Annotation

提到annotation想必大家都不会陌生,因为基本上JAVA的工程中随处可见annotation的身影。

  • Override: 这个annotation表明此方法是在接口中声明过或者抽象类中需要被实现的
  • Autowired: spring框架中,声明某个方法或者属性是作为bean存在的
  • Data/getter: lomok包里面的,省去书写getter和setter等的annotation

annotation实际上是利用了Java的反射原理,来对类的属性等遍历进行处理。

Annotation 含义

An annotation is a marker which associates information with a program construct, but has no effect at run time.

annotation是用来标记程序代码的相关信息的标识符。annotation不会对程序的运行时产生影响。但是它会给运行时代码提供信息。

构造一个Annotation

我们来了解一下如何构造一个新的Annotation,这样就可以对经常使用的@Autowired @Data等原理有一个了解。

示例如下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Rename {
    public String value() default "";
}
  • @interface:表明这是一个annotation的声明
  • @Retention:表明这个annotation的生命周期,RUNTIME是指在整个运行时,后续会看到Retention会有其他的几个类型
  • Target: 表明这个annotation会在哪些范围起作用,FIELD指的是属性上起作用
  • value: 表明了属性有一个对应的String类型的值,默认为空字符串

有了这个定义,我们可以在属性上来使用:

public class Building {

    @Rename("bName")
    private String name;

    @Rename("bCity")
    private String city;


private Integer height;
}

Annotation的处理

上面我们只看到,定义了一个annotation,那么对于像Autowired这种,是在什么地方去处理的呢,下面我们就来展示一下,通过Rename这个annotation来打印所有的属性的别名。

  • 拿到Building对象对应的类

  • 获取所有的属性

  • 设置属性为可读

  • 获取annotation对应的值

  • 输出结果

    public String process(Object object) {
    
      Class aClass = requireNonNull(object).getClass();
    
    
      List properties = Arrays.asList(aClass.getDeclaredFields())
              .stream()
              .filter(field -> field.isAnnotationPresent(Rename.class))
              .map(field -> {
                  field.setAccessible(true);
                  try {
                      return field.getAnnotation(Rename.class).value() + ": " + field.get(object);
                  } catch (IllegalAccessException e) {
                      e.printStackTrace();
                      return "";
                  }
              })
              .collect(Collectors.toList());
    
      return String.join("\r\n", properties);
    }
    

可以查看一下结果:

@Test
public void shouldRenameBuilding() {
ProcessRename processRename = new ProcessRename();

    Building building = new Building();
    building.setCity("sydney");
    building.setName("kongn");

    String process = processRename.process(building);
    System.out.println(process);
}

输出结果:

bName: kongn
bCity: sydney

Retention和Target

  • Rentention的类型有如下三种:
Policy Description
Source Annotations 会被编译器丢弃掉,例如@override
Class Annotations只在编译期起作用
Runtime Annotations被编译器标记为在运行时起作用
  • Target的类型:
Target Description
Annotation Type Annotates another annotation
Constructor Annotates a constructor
Field Annotates a field, such as an instance variable of a class or an enum constant
Local variable Annotates a local variable
Method Annotates a method of a class
Module Annotates a module (new in Java 9)
Package Annotates a package
Parameter Annotates a parameter to a method or constructor
Type Annotates a type, such as a class, interfaces, annotation types, or enum declarations
Type Parameter Annotates a type parameter, such as those used as formal generic parameters
Type Use Annotates the use of a type, such as when an object of a type is created using the newkeyword, when an object is cast to a specified type, when a class implements an interface, or when the type of a throwable object is declared using the throws keyword (for more information, see the Type Annotations and Pluggable Type Systems Oracle tutorial)

你可能感兴趣的:(Java的Annotation)