更新时间:2022-07-01 11:05:54 来源:极悦 浏览2128次
如何创建Java自定义注解?极悦小编来为大家解答。Java 中的注释是一种将元数据信息添加到我们的源代码的机制。它们是 JDK5 中添加的 Java 的一个强大部分。注释提供了使用 XML 描述符和标记接口的替代方法。
虽然我们可以将它们附加到包、类、接口、方法和字段上,但注释本身对程序的执行没有影响。
在本教程中,我们将重点介绍如何创建和处理自定义注释。我们可以在关于注释基础的文章中阅读更多关于注释的信息。
我们将创建三个自定义注释,目标是将对象序列化为 JSON 字符串。
我们将在类级别使用第一个,向编译器指示我们的对象可以被序列化。然后我们将第二个应用到我们想要包含在 JSON 字符串中的字段。
1.类级别注释示例
创建自定义注解的第一步是使用@interface关键字声明它:
public @interface JsonSerializable {
}
下一步是添加元注释来指定我们自定义注释的范围和目标:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.Type)
public @interface JsonSerializable {
}
如我们所见,我们的第一个注解具有运行时可见性,我们可以将其应用于类型(类)。此外,它没有方法,因此可以作为一个简单的标记来标记可以序列化为 JSON 的类。
(2)字段级注释示例
以同样的方式,我们创建第二个注释来标记我们将包含在生成的 JSON 中的字段:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JsonElement {
public String key() default "";
}
注释声明了一个名为“key”的字符串参数和一个空字符串作为默认值。
在使用方法创建自定义注解时,我们应该注意这些方法必须没有参数,并且不能抛出异常。此外,返回类型仅限于这些类型的基元、字符串、类、枚举、注释和数组, 默认值不能为 null。
(3)方法级别注释示例
假设在将对象序列化为 JSON 字符串之前,我们想要执行一些方法来初始化对象。出于这个原因,我们将创建一个注释来标记这个方法:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Init {
}
我们声明了一个具有运行时可见性的公共注释,我们可以将其应用于类的方法。
(4)应用注释
现在让我们看看如何使用我们的自定义注解。例如,假设我们有一个Person类型的对象 ,我们想将其序列化为 JSON 字符串。这种类型有一个方法可以将名字和姓氏的第一个字母大写。我们需要在序列化对象之前调用这个方法:
@JsonSerializable
public class Person {
@JsonElement
private String firstName;
@JsonElement
private String lastName;
@JsonElement(key = "personAge")
private String age;
private String address;
@Init
private void initNames() {
this.firstName = this.firstName.substring(0, 1).toUpperCase()
+ this.firstName.substring(1);
this.lastName = this.lastName.substring(0, 1).toUpperCase()
+ this.lastName.substring(1);
}
// Standard getters and setters
}
通过使用我们的自定义注释,我们表明我们可以将 Person 对象序列化为 JSON 字符串。此外,输出应仅包含该对象的firstName、lastName和age字段。此外,我们希望在序列化之前调用initNames()方法。
通过将@JsonElement注释的关键参数设置为“personAge”,我们表明我们将使用此名称作为JSON 输出中字段的标识符。
为了演示,我们将initNames() 设为私有,因此我们不能通过手动调用来初始化我们的对象,而且我们的构造函数也没有使用它。
到目前为止,我们已经了解了如何创建自定义注释,以及如何使用它们来装饰Person类。现在我们将了解如何通过使用 Java 的反射 API 来利用它们。
第一步是检查我们的对象是否为空,以及它的类型是否有 @JsonSerializable注解:
private void checkIfSerializable(Object object) {
if (Objects.isNull(object)) {
throw new JsonSerializationException("The object to serialize is null");
}
Class<?> clazz = object.getClass();
if (!clazz.isAnnotationPresent(JsonSerializable.class)) {
throw new JsonSerializationException("The class "
+ clazz.getSimpleName()
+ " is not annotated with JsonSerializable");
}
}
然后我们寻找任何带有@Init 注解的方法,并执行它来初始化我们对象的字段:
private void initializeObject(Object object) throws Exception {
Class<?> clazz = object.getClass();
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(Init.class)) {
method.setAccessible(true);
method.invoke(object);
}
}
}
方法的调用 。setAccessible ( true)允许我们执行私有的initNames()方法。
初始化后,我们遍历对象的字段,检索 JSON 元素的键和值,并将它们放入映射中。然后我们从地图创建 JSON 字符串:
private String getJsonString(Object object) throws Exception {
Class<?> clazz = object.getClass();
Map<String, String> jsonElementsMap = new HashMap<>();
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
if (field.isAnnotationPresent(JsonElement.class)) {
jsonElementsMap.put(getKey(field), (String) field.get(object));
}
}
String jsonString = jsonElementsMap.entrySet()
.stream()
.map(entry -> "\"" + entry.getKey() + "\":\""
+ entry.getValue() + "\"")
.collect(Collectors.joining(","));
return "{" + jsonString + "}";
}
同样,我们使用了 field。setAccessible ( true )因为Person对象的字段是私有的。
我们的 JSON 序列化程序类结合了上述所有步骤:
public class ObjectToJsonConverter {
public String convertToJson(Object object) throws JsonSerializationException {
try {
checkIfSerializable(object);
initializeObject(object);
return getJsonString(object);
} catch (Exception e) {
throw new JsonSerializationException(e.getMessage());
}
}
}
最后,我们运行一个单元测试来验证我们的对象是否按照自定义注释的定义进行了序列化:
@Test
public void givenObjectSerializedThenTrueReturned() throws JsonSerializationException {
Person person = new Person("soufiane", "cheouati", "34");
ObjectToJsonConverter serializer = new ObjectToJsonConverter();
String jsonString = serializer.convertToJson(person);
assertEquals(
"{\"personAge\":\"34\",\"firstName\":\"Soufiane\",\"lastName\":\"Cheouati\"}",
jsonString);
}
以上就是关于“创建Java自定义注解”的介绍,大家如果对此比较感兴趣,想了解更多相关知识,不妨来关注一下极悦的Java开发自定义注解,里面有更详细的介绍,希望对大家能够有所帮助哦。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习