Java 注解Annotation的使用

网友投稿 294 2022-09-18

Java 注解Annotation的使用

Java注解是一种用来给源码添加元数据的机制。所谓元数据就是用来描述源码中的包、类、接口、方法、字段的信息。这些注解的添加不会影响程序的执行。

我们用一个例子来说明如何自定义注解以及如何处理注解。我们这个例子是关于如何将一个对象转成Json的。

自定义注解

1. 首先,定义一个class级别的注解,用于标识某个类是否能序列化成Json字符串。

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

定义一个注解时,要使用​​@interface​​​关键字。除了定义我们自己的注解之外,我们还可以用JDK提供的注解来为自定义注解添加些元数据,以此来说明自定义注解的用途。因为我们这个注解是在运行程序的过程中需要使用的,那么我们这个注解的可见性就是在运行时,所以我们可以加上这个注解​​@Retention(RetentionPolicy.RUNTIME)​​​ 因为我们打算把这个注解应用在类上,那么我们可以加上这个注解​​​@Target(ElementType.TYPE)​​,这样之后,系统会检查这个自定义注解是否用在类上了。

2. 接着,再定义一个field级别的注解,用于指定该字段在Json中的键。

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface JsonField { String key() default "";}

我们这个注解有一个特别的地方,就是定义 一个方法​​key()​​,它不能有参数,也不能抛异常,而且它返回的类型必须是原始类型、String、类、枚举、注解、或者是这些类型的数组,默认值不能为null。

3.最后,定义一个method级别的注解,用于标识某个方法要在序列化前被执行。

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

在一个类上应用以上注解

package com.example.customannotationjava;@SerializableJSONpublic class Student { @JsonField private String lastName; @JsonField private String firstName; @JsonField(key = "fullName") private String name; @JsonField(key = "home") private String address; @JsonField private int age; private String school; @BeforeSerializable private void initFullName(){ name = lastName + firstName+"@"; }// 省略gettters / setters}

@SerializableJSON:通过此注解标识Student类可能被序列化为json@JsonField:标了此注解的字段都会出现在json中,因为school字段没有被标记,所以它不会出现在json中,另外有些字段在json出现的键不是类中的字段名,如address,在json里的键是home。@BeforeSerializable: 这个方法会在序列前执行。我将其的可见性标成了private,这意味着我们无法手动调用,并且在这里,我也没有在构造方法里调用它,那么它只能够在我处理注解时调用了。^_^

处理注解

上面提到的注解将会如何被处理,就是现在要讲的。也就是如果只定义注解而没有相应的注解处理实现,那么一切都是空谈。

1.检查将要序列化的对象的类是否标记了​​@SerializableJSON​​

private void checkIfSerializable(Object object) throws Exception { if(object == null){ throw new Exception("The object to serialize is null"); } Class clazz = object.getClass(); if(!clazz.isAnnotationPresent(SerializableJSON.class)){ throw new Exception(clazz.getSimpleName()+" is not annotated with SerializableJSON"); } }

2.首先处理标记了​​@BeforeSerializable​​的方法,这是做序列化前要做的事

private void executeInitialMethod(Object object) throws Exception { if(object == null){ throw new Exception("The object to serialize is null"); } Class clazz = object.getClass(); for(Method method:clazz.getDeclaredMethods()){ if(method.isAnnotationPresent(BeforeSerializable.class)){ method.setAccessible(true); method.invoke(object); } } }

​​method.setAccessible(true)​​可以执行对象中的private方法。

3.将对象中的字段与对应的值,记录在map中,再拼成json

private String getJsonString(Object object) throws Exception { if (object == null) { throw new Exception("The object to serialize is null"); } Class clazz = object.getClass(); Map map = new HashMap<>(); for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); if (field.isAnnotationPresent(JsonField.class) && field.get(object) != null) { String key = getKey(field); if(!TextUtils.isEmpty(key)) { map.put(key, field.get(object)); } } } String json = map.entrySet().stream().map(stringStringEntry ->{ String a = "\"" + stringStringEntry.getKey() + "\":"; Object b = null; if(stringStringEntry.getValue() != null){ if(stringStringEntry.getValue() instanceof String){ b = "\""+stringStringEntry.getValue()+"\""; }else{ b = stringStringEntry.getValue(); } } return a + b; }) .collect(Collectors.joining(",")); return "{" + json + "}"; } private String getKey(Field field) { JsonField jsonField = field.getAnnotation(JsonField.class); if (jsonField != null) { String key = jsonField.key(); if (key.length() == 0) { key = field.getName(); } return key; } return null; }

来个单元测试

package com.example.customannotationjava;import junit.framework.TestCase;public class JsonParserTest extends TestCase { public void testParseToJson() throws Exception { Student student = new Student("Wong","ban","GZ",18,"110Mid"); JsonParser jsonParser = new JsonParser(); String actual = jsonParser.parseToJson(student); String expected = "{\"lastName\":\"Wong\",\"firstName\":\"ban\",\"fullName\":\"Wong ban@\",\"age\":18,\"home\":\"GZ\"}"; assertEquals(expected,actual); }}

​​Demo​​

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:MBR分区、BootLoader程序、分区表
下一篇:mongodb的热备工具pbm-agent
相关文章

 发表评论

暂时没有评论,来抢沙发吧~