@Inherited는 어노테이션이 클래스에 적용될 때 해당 어노테이션이 하위 클래스에 상속될 수 있도록 한다. 기본적으로 어노테이션은 상속되지 않지만, @Inherited를 사용하면 부모 클래스에 적용된 어노테이션이 자식 클래스에도 적용된다.
@Inherited 어노테이션이 없는 경우, (1) 인터페이스를 상속받은 구현체 또는 (2) 자식 클래스에서 해당 어노테이션이 추가되어 있는 클래스를 찾을 수 없게 된다. 이를 확인하기 위해 Spring의 ApplicationContext를 사용하여 어노테이션을 찾는 예제로 확인해 본다.
1. @Inherited 없는 커스텀 어노테이션 정의
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface ShibaHolic {
String value();
}
2. 부모와 자식 클래스를 Bean으로 등록
@ShibaHolic("ParentClass")
@Component
class ParentClass {
}
@Component
class ChildClass extends ParentClass {
}
3. Spring ApplicationContext를 통해 Bean을 찾기
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class.getPackage().getName());
String[] beanNames = context.getBeanNamesForAnnotation(ShibaHolic.class);
for (String beanName : beanNames) {
System.out.println("Bean with ShibaHolic: " + beanName);
}
context.close();
}
}
위 코드에서는 ShibaHolic 어노테이션이 @Inherited로 정의되지 않았기 때문에, ChildClass는 ShibaHolic을 상속받지 않는다. 따라서 ApplicationContext에서 ShibaHolic이 붙은 빈을 찾을 때 ChildClass는 포함되지 않는다.
출력 결과는 부모 클래스 하나만 조회되게 된다.
Bean with MyAnnotation: parentClass
이런 경우, 어노테이션에 @Inherited를 추가하면 자식 어노테이션을 찾을 수 있다.
4. @Inherited 있는 커스텀 어노테이션 정의
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@interface ShibaHolic {
String value();
}
@Inherited가 있는 경우, 부모 클래스에 선언된 어노테이션이 자식 클래스에 상속되므로 Spring ApplicationContext에서 어노테이션을 찾을 때 자식 클래스도 포함된다.
다시 main()을 실행하면 다음과 같은 결과를 얻을 수 있다.
Bean with MyAnnotation: parentClass
Bean with MyAnnotation: childClass
@Inherited의 작동 원리 = 리플렉션
@Inherited 어노테이션은 Java 리플렉션 API와 함께 동작한다. Java 리플렉션 API는 런타임에 클래스, 메서드, 필드 등의 메타데이터를 검사하고 조작할 수 있는 기능을 제공한다. @Inherited는 이러한 리플렉션 API를 통해 부모 클래스의 어노테이션을 자식 클래스에 상속하는 역할을 한다.
리플렉션 API는 클래스의 메타데이터를 검사할 때 @Inherited 어노테이션이 적용된 경우, 부모 클래스의 어노테이션을 자식 클래스에서도 찾을 수 있도록 한다.
이와 같이 @Inherited는 리플렉션 API와 함께 동작하여 부모 클래스의 어노테이션을 자식 클래스에서도 사용할 수 있도록 한다. 이를 통해 코드의 재사용성과 일관성을 높일 수 있다.
Bean을 생성하고 어노테이션을 통해 자식 클래스까지 해당 어노테이션이 있는 경우 찾고자 하는 경우에는 @Inherited를 사용해야 하는 것을 잊지 말자.
'Java' 카테고리의 다른 글
MariaDB decimal 타입과 Java BigDecimal 동일하게 처리하기 (0) | 2023.08.05 |
---|---|
ObjectMapper readValue 다형성 적용하기 (+ Jackson2JsonRedisSerializer) (1) | 2023.07.16 |
댓글