ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2024.10.28 AOP Inheritance
    TIL 2024. 10. 29. 10:29

     

     

    추상클래스와 @transactional 질문입니다. - 인프런 | 커뮤니티 질문&답변

    누구나 함께하는 인프런 커뮤니티. 모르면 묻고, 해답을 찾아보세요.

    www.inflearn.com

     

    관련해서 개발하다가 궁금한 점이 생겼습니다.

     

    자식 클래스에 @Transactional 이 있고, 부모의 메서드를 오버라이딩하지 않았으면 그 메서드는 @Transactional AOP 범위에 포함되지 않습니다.

    Spring considers transactional. Note that a class-level annotation does not apply to ancestor classes up the class hierarchy;

     

     

    Using @Transactional :: Spring Framework

    The @Transactional annotation is metadata that specifies that an interface, class, or method must have transactional semantics (for example, "start a brand new read-only transaction when this method is invoked, suspending any existing transaction"). The de

    docs.spring.io

     

    사실 이렇게 구현한 명확한 이유는 모르겠습니다.

     

    다만 어떻게 구현되어 있는지가 궁금했습니다.


    처음 들었던 생각은 메모리였습니다.
    메모리에서 오버라이딩한 부모 메서드는 따로 관리가 되나? 하는 추론을 했습니다.

     

    메모리에서 오버라이딩하지 않은 메서드에 접근할 때 어떻게 호출..

    일단 하나의 힙영역에 부모와 자식이 전부 들어가는 것으로 보입니다. 

    결국 Object까지 올라갈 것으로 생각됩니다. 

    그럼 메소드 호출해도 결국 heap에 있는 메서드 정보를 사용해 method area에서 가져올 수 있을 것입니다.

    음 이 접근은 정답이 아닌 것 같습니다.

     

    Java memory usage in inheritance

    What does the memory usage look like in Java when extending a base class. Do the child class contain an instance of the base class (with it's own overhead and all) or does it only have it's own ov...

    stackoverflow.com

     

    노선을 바꿔서 AOP를 뜯어보면서 구현을 알게 되었습니다.

    • 요약하자면 오버라이딩을 하지 않으면 어노테이션을 찾을 때 부모의 클래스 기반으로 찾게 됩니다. 그러니 부모에 어노테이션이 없으면 없다고 나오는 것입니다.
    • 인프런 예제로 보면 Example 클래스의 메소드에는 [com.sample.ExampleClass.method2, com.sample.AbstractExampleClass.method1]이 있는 것 입니다.
    • AnnotatedElementUtils.findMergedAnnotationAttributes로 어노테이션을 찾아도 못찾는 이유입니다.

     

     

    동작을 따라가 보면..

     

    메서드를 실행시키기 전에 AOP가 있는지 확인하는 절차가 있습니다. Intercepter, chain이라고 부릅니다.

    Intercepter는 애플리케이션이 로딩될 때, 여부를 확인하고 주입하게 됩니다.

    모든 메서드에 Intercepter를 넣어주는 절차가 있다는 것입니다.

    이 작업은 Enhancer가 담당합니다.

    https://github.com/spring-projects/spring-framework/blob/4749d810db0261ce16ae5f32da6d375bb8087430/spring-core/src/main/java/org/springframework/cglib/proxy/Enhancer.java#L626

    ReflectUtils을 사용해 클래스의 모든 메서드를 가져오고, 하단에서 Static과 final 메서드는 필터링합니다.

    이 메서드를 호출하는 쪽으로 가보면..

    https://github.com/spring-projects/spring-framework/blob/4749d810db0261ce16ae5f32da6d375bb8087430/spring-core/src/main/java/org/springframework/cglib/proxy/Enhancer.java#L649
    https://github.com/spring-projects/spring-framework/blob/4749d810db0261ce16ae5f32da6d375bb8087430/spring-core/src/main/java/org/springframework/cglib/proxy/Enhancer.java#L1198

    emitMethods를 만날 수 있습니다. 

    filter는 CglibAopProxy입니다. 

    CglibAopProxy의 accept를 보면 다음과 같습니다.

    object의 상속된 메서드나, Advised 메서드를 필터링도 하고, Chain을 가지고 있다면 AOP_PROXY타입을 반환합니다.

    음 반환은 나중에 더 봐야겠습니다.

    더 중요한 것은 advised(AdvisedSupport). getInterceptorsDynamicInterceptionAdvice입니다.

     

    https://github.com/spring-projects/spring-framework/blob/4749d810db0261ce16ae5f32da6d375bb8087430/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java#L815

    AdvisedSupport class에서 method당 interceptors를 캐시 하는 역할을 합니다.

     

    https://github.com/spring-projects/spring-framework/blob/4749d810db0261ce16ae5f32da6d375bb8087430/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java#L520

     

    실질적으로는 DefaultAdvisorChainFactory에 의해서 chain을 추출할 수 있습니다.

     

    https://github.com/spring-projects/spring-framework/blob/4749d810db0261ce16ae5f32da6d375bb8087430/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAdvisorChainFactory.java#L58

     

     

    다만 parent.method이기 때문에 자식에서 정의한 transactional은 찾을 수 없게 됩니다.

    오버라이딩을 했다면 child.method로 표시되고 match내부에서 annotation기반으로 찾게 된다.

    찾는 것을 따라가다 보면 SpringTransactionAnnotationParser에서 어노테이션이 달려있는지 확인하게 됩니다.

    https://github.com/spring-projects/spring-framework/blob/4749d810db0261ce16ae5f32da6d375bb8087430/spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java#L70
    https://github.com/spring-projects/spring-framework/blob/015beb0058f897bf557b50fc84c6163218f7c800/spring-tx/src/main/java/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java#L164


    클래스와 메소드에서 transaction 어노테이션이 붙어있는지 확인합니다.

    'TIL' 카테고리의 다른 글

    2024.11.01 Query tuning  (0) 2024.11.02
    2024.10.29 JWT  (0) 2024.10.30
    2024.10.23 ElasticSearch, Apache Lucene  (0) 2024.10.23
    2024.10.22 system design  (0) 2024.10.22
    2024.10.21 ssl replay attack  (0) 2024.10.21

    댓글

Designed by Tistory.