인프런 커뮤니티 질문&답변

raifado님의 프로필 이미지
raifado

작성한 질문수

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

AOP 적용

AOP(TimeTraceAop)를 @Component 로 선언 vs SpringConfig에 @Bean으로 등록

작성

·

3.6K

41

안녕하세요. 김영한 팀장님, 

AOP(TimeTraceAop)를 @Component로 선언하지 않고

SpringConfig에 @Bean으로 등록할 수 있다고 설명하셨는데 실제로 코드를 돌려보면 빈 순환 참조 에러가 발생합니다.

강의대로 @Component로만 선언하면 문제가 없는데

왜 순환참조가 나는지 질문드립니다.

감사합니다.

The dependencies of some of the beans in the application context form a cycle:

   memberController defined in file [~~~\out\production\classes\com\example\springexample\controller\MemberController.class]

      ↓

   memberService defined in class path resource [com/example/springexample/SpringConfig.class]

┌─────┐

|  timeTraceAop defined in class path resource [com/example/springexample/SpringConfig.class]

답변 11

99

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. raifado님 좋은 질문입니다.

직접 @Bean으로 등록했을 때 순환참조가 발생하는 이유는 다음과 같습니다.

@Configuration

public class SpringConfig {

    @Bean
    public TimeTraceAop timeTraceAop() {
        return new TimeTraceAop();
    }
}

@Aspect
public class TimeTraceAop {

    @Around("execution(* hello.hellospring..*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable { }
}

TimeTraceAop의 AOP 대상을 지정하는 @Around 코드를 보시면, SpringConfig의 timeTraceAop() 메서드도 AOP로 처리하게 됩니다. 그런데 이게 바로 자기 자신인 TimeTraceAop를 생성하는 코드인 것이지요. 그래서 순환참조 문제가 발생합니다.

반면에 컴포넌트 스캔을 사용할 때는 AOP의 대상이 되는 이런 코드 자체가 없기 때문에 문제가 발생하지 않았습니다.

그러면 AOP 설정 클래스를 빈으로 직접 등록할 때는 어떻게 문제를 해결하면 될까요? 바로 다음과 같이 AOP 대상에서 SpringConfig를 빼주면 됩니다.

@Aspect
public class TimeTraceAop {


    @Around("execution(* hello.hellospring..*(..)) && !target(hello.hellospring.SpringConfig)")

    //@Around("execution(* hello.hellospring..*(..))")

    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {...}

}

도움이 되셨길 바래요^^

감사합니다!!

완벽히 이해했습니다. 감사합니다!

5

스프링부트 2.1 부터는 overriding 옵션이 false로 default 설정이 된다고 하네요.

https://n1tjrgns.tistory.com/172

 

SpringConfig.java에서 "@Bean public TimeTraceAop"  만들 때는

"@Component public class TimeTraceAop " 여기서  추가로 Bean이 

중복 생성되므로 둘 중 한쪽 Bean은 제거해야 합니다.
("스프링입문_강의자료.pdf" 의 61쪽에  "@Component @Aspect public class TimeTraceAop" 만 있고 SpringConfig.java에 "@Bean public TimeTraceAop" 을 생성하지 않았네요.  )


SpringConfig.java에서 "@Bean public TimeTraceAop" 사용하려면  @Component 삭제 하거나 

application.properties의

spring.main.allow-bean-definition-overriding=true

추가 하면 된다고 하네요.

뒤늦게 합류한 사람인데 다알님 댓글로 해결했어요

감사합니다

1

raifado님의 프로필 이미지
raifado
질문자

아 이해되었습니다~! 감사합니다.

0

같은 현상에 대해 해결 되었습니다. 감사합니다!

0

같은 현상이 있어, 질문 올리려다 찾았습니다.

감사합니다!

0

같은거 찾고있었는데 감사합니다

0

저도 이거 찾고 있었는데 도움이 되었습니다.

감사합니다.

0

순환참조 문제가 발생한 점을 캐치하신 점도 본받아야겠습니다.

0

우와 한참찾았는데 감사합니다 !!

0

저도 같은 고민인데 감사합니다~

0

같은 고민을 하고 있었는데 이 질문, 답변을 통해 해결했습니다. 감사합니다.

raifado님의 프로필 이미지
raifado

작성한 질문수

질문하기