티스토리 뷰

Java

[Java] @ annotation

조용한스택 2023. 7. 5. 14:10

개발 중 어노테이션을 사용해서 AOP를 적용해보려다 어노테이션에 대해 알고 가는 게 좋을 것 같아 스터디한 내용이다.


어디에 사용할 수 있는지?

  • Class instance creation expression
  • new @Interned MyObject();
  • Type cast
  • myString = (@NonNull String) str;
  • implements clause
  • class UnmodifiableList<T> implements @Readonly Llist<@Readonly T> { ... }
  • Thrown exception declaration
  • void monitorTemperature() throws @Critical TemperatureException { ... }
  • @interface는 자동으로 Annotation 클래스를 상속(확장)하며, 내부의 메소드들은 abstract 키워드가 자동으로 붙게 된다
  • 추가적인 정보를 제공해주는 메타데이터. 그 자체로는 아무것도 하지 않는다. 띠용
  • 어노테이션에 대한 접근은 리플렉션으로만 가능하다.

정의되어 있는 어노테이션 타입

  • Deprecated
  • Override
  • SuppressWarnings

repeating annotation

  • 같은 어노테이션을 여러 번 사용
  • 중복해서 설정하고 싶은 경우 사용
  • 예: @Schedule, @Alert

어노테이션에 붙은 어노테이션

  • @Documented : Java doc에 문서화 여부를 결정
  • @Target: 어노테이션 사용 대상
  • @Retention: 어노테이션의 지속 시간
    • 리플렉션 사용하려면 RetentionPolicy.RUNTIME 설정해야 함
      • SOURCE: 코드에서만 보이고, 컴파일 후 바이트 코드에서는 없다.
      • CLASS: 컴파일 후인 바이트 코드 (.class)까지 존재. 그러나 런타임 때는 없다. 바이트 코드에서 작업이 필요한 경우. 리플렉션 불가

 

사용 케이스

주석을 어노테이션으로 대체

@Component (spring)

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
    String value() default "";
}

ClassPathBeanDefinitionScanner.doScan()
ClassPathScanningCandidateComponentProvider.scanCandidateComponents()
ClassPathScanningCandidateComponentProvider.isCandidateComponent() includeFilters와 일치하는지 확인
ClassPathScanningCandidateComponentProvider.registerDefaultFilters() Component 어노테이션을 includeFilters에 담는 로직

어노테이션으로 AOP 구현

  • Target: 주입할 대상
  • Advice: 횡단 관심사
  • JoinPoint: 어드바이스가 적용될 수 있는 위치
  • PointCut: 어드바이스를 적용할 선정하는 방법

해보기

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface NotifyExceptionToSlack {
}
@Aspect
@Slf4j
@Component
public class NotifyExceptionToSlackAdvisor {

    @Around("@annotation(com.example.annotation.NotifyExceptionToSlack)")
    public void process(ProceedingJoinPoint proceedingJoinPoint) throws Exception {
        try {
            log.debug("-------------------------------------------------------------------------");
            log.debug("[DEBUG] annotation AOP processed!!");
            log.debug("[DEBUG] method name: {}", proceedingJoinPoint.getSignature());
            proceedingJoinPoint.proceed();
        } catch (Exception e) {
            SlackService.debug(e.getMessage(), SlackService.SYSTEM_REPORT_CHANNEL);
            throw e;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

}

적용 아이디어

  • SecurityConfig에 로그인 체크 x api에 어노테이션 추가
  • dto 중 request 만 받을 수 있게 설정하는 어노테이션
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
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 31
글 보관함