Java로 사용자 지정 주석 만들기

1. 소개

Java 주석은 소스 코드에 메타 데이터 정보를 추가하기위한 메커니즘입니다. Java의 강력한 부분이며 JDK5에 추가되었습니다. 주석은 XML 설명자 및 마커 인터페이스 사용에 대한 대안을 제공합니다.

패키지, 클래스, 인터페이스, 메서드 및 필드에 연결할 수 있지만 주석 자체는 프로그램 실행에 영향을주지 않습니다.

이 자습서에서는 사용자 지정 주석을 만드는 방법과이를 처리하는 방법에 중점을 둘 것입니다. 주석 기본 사항에 대한 기사에서 주석에 대해 자세히 알아볼 수 있습니다.

2. 사용자 지정 주석 만들기

객체를 JSON 문자열로 직렬화 할 목적으로 세 가지 사용자 지정 주석을 만들 것입니다.

우리는 객체가 직렬화 될 수 있음을 컴파일러에 알리기 위해 클래스 수준에서 첫 번째 것을 사용할 것입니다. 다음으로 두 번째 항목을 JSON 문자열에 포함 할 필드에 적용합니다.

마지막으로, 메서드 수준에서 세 번째 주석을 사용하여 객체를 초기화하는 데 사용할 메서드를 지정합니다.

2.1. 클래스 수준 주석 예

사용자 지정 주석을 만드는 첫 번째 단계 @interface 키워드를 사용하여 선언하는 것입니다 .

public @interface JsonSerializable { }

다음 단계는 사용자 지정 주석 의 범위와 대상을 지정 하기 위해 메타 주석추가하는 것 입니다.

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.Type) public @interface JsonSerializable { }

보시다시피 첫 번째 주석 에는 런타임 가시성이 있으며 유형 (클래스)에 적용 할 수 있습니다 . 또한 메서드가 없으므로 JSON으로 직렬화 할 수있는 클래스를 표시하는 간단한 마커 역할을합니다.

2.2. 필드 수준 주석 예

같은 방식으로 생성 된 JSON에 포함 할 필드를 표시하기 위해 두 번째 주석을 만듭니다.

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

주석은 "key"라는 이름을 가진 하나의 String 매개 변수와 기본값으로 빈 문자열을 선언합니다.

메서드로 사용자 지정 주석을 만들 때 이러한 메서드에는 매개 변수가 없어야하며 예외를 throw 할 수 없습니다 . 또한 반환 유형은 이러한 유형의 기본, 문자열, 클래스, 열거 형, 주석 및 배열로 제한되며 기본값은 null이 될 수 없습니다 .

2.3. 메서드 수준 주석 예

객체를 JSON 문자열로 직렬화하기 전에 객체를 초기화하는 메서드를 실행한다고 가정 해 보겠습니다. 따라서이 메서드를 표시하는 주석을 만들 것입니다.

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

우리는 클래스의 메서드에 적용 할 수있는 런타임 가시성을 가진 공개 주석을 선언했습니다.

2.4. 주석 적용

이제 사용자 지정 주석을 사용하는 방법을 살펴 보겠습니다. 예를 들어 JSON 문자열로 직렬화하려는 Person 유형의 객체가 있다고 가정 해 보겠습니다 . 이 유형에는 성과 이름의 첫 글자를 대문자로 사용하는 방법이 있습니다. 객체를 직렬화하기 전에이 메서드를 호출해야합니다.

@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 , lastNameage 필드 만 포함되어야합니다 . 또한 직렬화 전에 initNames () 메서드가 호출 되기를 원합니다 .

@JsonElement 주석 의 매개 변수 를 "personAge"로 설정하여이 이름을 JSON 출력의 필드 식별자로 사용할 것임을 나타냅니다.

데모를 위해 initNames ()를 private으로 만들었 으므로 개체를 수동으로 호출하여 초기화 할 수 없으며 생성자도 사용하지 않습니다.

3. 주석 처리

지금까지 사용자 지정 주석을 만드는 방법과이를 사용하여 Person 클래스 를 장식하는 방법을 살펴 보았습니다 . 이제 Java의 Reflection API를 사용하여이를 활용하는 방법을 살펴 보겠습니다.

첫 번째 단계는 객체 유형이 @JsonSerializable 어노테이션 이 있는지 여부와 함께 객체가 null 인지 여부를 확인하는 것입니다 .

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 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 를 사용 했습니다 . Person 객체의 필드가 비공개 이기 때문에 setAccessible ( tru e ) .

JSON serializer 클래스는 위의 모든 단계를 결합합니다.

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"); JsonSerializer serializer = new JsonSerializer(); String jsonString = serializer.serialize(person); assertEquals( "{\"personAge\":\"34\",\"firstName\":\"Soufiane\",\"lastName\":\"Cheouati\"}", jsonString); }

4. 결론

이 기사에서는 다양한 유형의 사용자 지정 주석을 만드는 방법을 살펴 보았습니다. 그런 다음 그것들을 사용하여 물건을 장식하는 방법에 대해 논의했습니다. 마지막으로 Java의 Reflection API를 사용하여 처리하는 방법을 살펴 보았습니다.

항상 그렇듯이 전체 코드는 GitHub에서 사용할 수 있습니다.