提到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<String> 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 new keyword, 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) |
网友评论