본문 바로가기

기술 블로그

Java Annotation

안녕하세요.

이번 글에서는 자바의 어노테이션에 대해서 분석한 내용을 정리해보고자 합니다. 순서는 아래와 같습니다.

  • Annotation의 동작 및 속성
  • @Transactional이 인식되는 과정

어노테이션의 기본 속성 및 주요 예시인 @Transactional 어노테이션의 인식 과정에 대해서 정리하였습니다.

 

1. Annotation의 동작 및 속성

어노테이션은 클래스, 생성자, 메소드 등 특정 위치에 정의될 수 있으며, 정책에 따라서 컴파일 타임에 적용되거나 리플렉션 활용하여 런타임에 접근될 수 있습니다. 예시는 아래와 같습니다.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration

 

  • Retention 정책

어노테이션을 어디까지 유지할 것인지를 결정하는 속성입니다. 어노테이션의 @Retention을 통해 지정할 수 있습니다.

  1. RetentionPolicy.SOURCE : 컴파일 시점에 사용된 후 어노테이션은 제거됩니다.
  2. RetentionPolicy.CLASS : 컴파일 후 클래스 파일까지 어노테이션이 포함되나, 런타임에는 활용할 수 없습니다.
  3. RetentionPolicy.RUNTIME : 런타임에도 리플렉션을 통해서 접근이 가능합니다.
  • 위치 정책

어노테이션을 어느 위치에 적용할 수 있는지를 결정하는 속성입니다. @Target을 통해서 지정할 수 있습니다. 예를 들어, 타입(클래스, 인터페이스, Enum), 필드, 메소드, 파라미터, 생성자 등에 적용할 수 있도록 지정이 가능합니다. 

 

 

2. @Transactional이 인식되는 과정

어노테이션이 어떻게 활용되는지 파악하기 위해 대표적인 어노테이션 @Transactional이 인식되는 방식에 대해서 확인했습니다. 아래 클래스를 확인해보면, 트랜잭션 관련 클래스 및 메소드는 AOP를 활용하여 Advisor로 등록되고 있음을 확인했습니다.

public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    
    @Bean
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(transactionAttributeSource);
        advisor.setAdvice(transactionInterceptor);
        if (this.enableTx != null) {
            advisor.setOrder((Integer)this.enableTx.getNumber("order"));
        }

        return advisor;
    }
}
  • Pointcut : @Transactional이 적용된 메소드 또는 클래스를 찾음
  • Advice : 트랜잭션 관련 정책을 적용함

 위 소스만을 놓고 보았을 때, TransactionAttributeSource가 내부적으로 Pointcut 처럼 동작하여 @Transactional 어노테이션이 붙은 메소드 및 클래스를 찾고 transactionInterceptor가 advice로 동작하여 트랜잭션 정책을 관리할 것으로 짐작되었습니다.

 

예상과 동일하게 BeanFactoryTransactionAttributeSourceAdvisor 객체 내 Pointcut 필드가 @Trasactional이 붙어 있는 메소드 또는 클래스와 그것의 속성(isolation, progatation 등)을 조회하고 있었습니다.

class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
    private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut();
	// ...
}

class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
    public boolean matches(Method method, Class<?> targetClass) {
        return this.transactionAttributeSource == null || this.transactionAttributeSource.getTransactionAttribute(method, targetClass) != null;
    }
}

class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource implements Serializable {
    protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
        for(TransactionAnnotationParser parser : this.annotationParsers) {
            TransactionAttribute attr = parser.parseTransactionAnnotation(element);
            if (attr != null) {
                return attr;
            }
        }
        return null;
    }
}

class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
        AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(element, Transactional.class, false, false);
        return attributes != null ? this.parseTransactionAnnotation(attributes) : null;
    }
 }

 

 

 

 

'기술 블로그' 카테고리의 다른 글

@Transactional Deep Dive  (1) 2025.02.19
Java ObjectMapper (Feat. RedisTemplate)  (1) 2025.02.13
스프링 Kafka Consumer Deep Dive - 1  (1) 2025.02.05
Spring Security에서의 Filter  (0) 2024.12.17
필터와 인터셉터란?  (0) 2024.12.11