Java

[Java] @Inherited 어노테이션

향각산 2023. 12. 8. 20:52

@Inherited 어노테이션이란?

설명

Java에서 사용하는 meta annotatino입니다.

meta annotation은 다른 annotation을 위한 annotation을 말합니다.

 

목적

특정 annotation을 상속 가능(inheritable) 하도록 만들 때 사용합니다.

사용 방식

특정 annotation에 @Inherited를 추가합니다.

제한사항

클래스 수준의 annotation에만 적용 가능합니다. 메소드나 필드 수준의 annotation에는 적용되지 않습니다.

인터페이스에 사용해도 구현체에는 상속되지 않습니다.

 

 테스트를 해보면 다음과 같다.

 

@Inherited 예시 코드

MyInheritedAnnotation이란 커스텀 어노테이션을 만들고, @Inherited를 추가합니다.

그리고 ParentClass에서 해당 커스텀 어노테이션을 사용합니다.

그 후 ChildClass를 만들어서 ParentClass를 상속받고, 해당 ChildClass가 처음에 만든 MyInheritedAnnotation에게 영향을 받고 있는지 확인하는 테스트를 진행합니다.

@Inherited
@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyInheritedAnnotation {
// 커스텀 어노테이션
}

@MyInheritedAnnotation
public class ParentClass {
// 커스텀 어노테이션을 사용하는 클래스
}

public class ChildClass extends ParentClass {
// 커스텀 어노테이션을 사용하는 클래스를 상속 받음.
}
public class AnnotationTest {

    @Test
    public void testInheritedAnnotation() {
        // ParentClass에 @MyInheritedAnnotation이라는 커스텀 어노테이션이 존재하는지?
        assertTrue(ParentClass.class.isAnnotationPresent(MyInheritedAnnotation.class));
        // ChildClass에 마찬가지로 @MyInheritedAnnotatino이 존재하는지 확인.
        assertTrue(ChildClass.class.isAnnotationPresent(MyInheritedAnnotation.class));

    }
}

 

위와 같은 테스트 코드는 성공합니다. MyInheritedAnnotation에 @Inherited 어노테이션이 존재하기 때문에, 해당 어노테이션을 사용하는 클래스 (ParentClass)를 상속받은 ChildClass도 @MyInheritedAnnotatino을 추가한 것과 마찬가지이기 때문입니다.

 

 

@Inherited를 제거

아래와 같이 Inherited를 제거하면 어떻게 될까요?

@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyInheritedAnnotation {

}

테스트 코드를 아래처럼 수정해야 합니다.

자세히보시면 두 번째 ChildClass를 비교하는 데이터가 assertFalse로 변경된 것을 확인할 수 있습니다.

ChildClass는 수정하지 않았지만, MyInheritedAnnotation에 @Inherited가 없어서 상속받아지지 않았습니다.

public class AnnotationTest {

    @Test
    public void testInheritedAnnotation() {
        assertTrue(ParentClass.class.isAnnotationPresent(MyInheritedAnnotation.class));
		// assertFalse
        assertFalse(ChildClass.class.isAnnotationPresent(MyInheritedAnnotation.class));
    }

}

 

 

@Inherited를 사용한 annotatino을 상속

여기서 개인적으로 궁금한건 MyInheritedAnnotation을 사용하는 annotation은 MyInheritedAnnotation에 적용된 Inherited가 적용되는지였습니다.

@Inherited
@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyInheritedAnnotation {

}

@MyInheritedAnnotation
@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ExtendedAnnotation {

}

@ExtendedAnnotation
public class ParentClass {

}

public class ChildClass extends ParentClass {

}
public class AnnotationTest {

    @Test
    public void testInheritedAnnotation() {
    	// assertFalse
        assertFalse(ParentClass.class.isAnnotationPresent(MyInheritedAnnotation.class));
		// assertFalse
        assertFalse(ChildClass.class.isAnnotationPresent(MyInheritedAnnotation.class));
    }

}

결론은 애초에 잘못된 생각이었습니다.

 

@RestController로 예를 들면 다음과 같습니다.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

스프링 WEB에서 많이 사용하는 RestController annotatino을 사용할 땐, meta annotatino인 @Controller와 @ResponseBody가 지원하는 기능들을 사용할 수 있지만, 해당 @RestControlelr 어노테이션을 사용하는 클래스가 @Controller  @ResponseBody를 사용한다고 의미하는 것은 아닌 것과 같았습니다.

'Java' 카테고리의 다른 글

[Java] Java에서 List를 Array로 변경하기  (0) 2023.12.20
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함