다른 annotation 에서도 사용되는 annotation을 말하며 custom annotation을 생성할 때 주로 사용된다. @Target과 @Retention을 이용하여 meta-annotation을 적용할 수 있다
ElementType.PACKAGE : 패키지에 선언
ElementType.TYPE : 클래스, 인터페이스에 선언
ElementType.ANNOTATION_TYPE : annotation에 선언
ElementType.CONSTRUCTOR : 생성자에 선언
ElementType.FIELD : enum, 상수 포함 객체 필드에 선언
ElementType.LOCAL_VARIABLE : 지역변수에 선언
ElementType.METHOD : 메서드에 선언
ElementType.PARAMETER : 파라미터에 선언
ElementType.TYPE_PARAMETER : 매개변수의 타입에 선언
ElementType.TYPE_USE : 매개변수 사용시 선언
RetentionPolicy.RUNTIME : 런타임단계에서 메모리가 유지되고, 런타임이 종료되면 메모리도 사라진다.
RetentionPolicy.CLASS : 클래스 파일에 존재하고 런타임에는 메모리도 사라진다.
RetentionPolicy.SOURCE : 소스 코드에만 이용가능하고 컴파일 후에는 메모리도 사라진다.
메서드 실행 속도를 측정하고 로깅해주는 어노테이션을 만든다고 가정해보자. 먼저 custom annotation을 만들고, LoggingAspect에서 @Around("@annotation(org.prgrms.kdt.aop.TrackTime)") 설정을 해주고 사용할 곳에서 @TrackTime을 설정해주면 된다.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TrackTime {
}
@Aspect
@Component
public class LoggingAspect {
private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
@Around("@annotation(org.prgrms.kdt.aop.TrackTime)")
public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
logger.info("Before method called. {}", joinPoint.getSignature().toString());
long startTime = System.nanoTime();
Object result = joinPoint.proceed();
long endTime = System.nanoTime() - startTime;
logger.info("After method called with result => {} and time taken {} nanosecondx", result, endTime);
return result;
}
}
@Override
@TrackTime
public Optional<Voucher> save(Voucher voucher) {
saveStorage(voucher);
return Optional.ofNullable(storage.put(voucher.getVoucherId(), voucher));
}
transactionManager, transactionTemplate 을 이용하여 transcation 을 이용한 transaction 처리는 프로그래머틱하다고 볼 수 있다.
@Transactional 을 이용한 방법을 의미한다.