public Long join(Member member){ long start = System.currentTimeMillis(); try{ // 같은 이름이 있는 중복 회원은 안된다. validateDuplicateMember(member); memberRepository.save(member); return member.getId(); } finally{ long finish = System.currentTimeMillis(); long timeMs = finish - start; System.out.println("join = " + timeMs + "ms"); } }
문제
AOP 적용
시간 측정 AOP 등록
정형화 되지 않고 특수한 기능들은 컴포넌트 스캔 보다 직접 자바 빈으로 등록
SpringConfig
package hello.hellospring; import hello.hellospring.aop.TimeTraceAop; import hello.hellospring.repository.*; import hello.hellospring.service.MemberService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class SpringConfig { private final MemberRepository memberRepository; @Autowired public SpringConfig(MemberRepository memberRepository){ this.memberRepository = memberRepository; } @Bean public MemberService memberService(){ return new MemberService(memberRepository); } @Bean public TimeTraceAop timeTraceAop(){ return new TimeTraceAop(); } // @Bean // public MemberRepository memberRepository(){ // return new MemoryMemberRepository(); // return new JdbcMemberRepository(dataSource); // return new JdbcTemplateMemberRepository(dataSource); // return new JpaMemberRepository(em); // return // } }
TimeTraceAop
package hello.hellospring.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Aspect //@Component public class TimeTraceAop { @Around("execution(* hello.hellospring..*(..)) && !target(hello.hellospring.SpringConfig)") // 공통 관심 사항을 어디에 적용 할지 ( 패키지명 + 클래스명 + 파라미터 타입 등등) -> 현재 패키지 하위에는 다 적용 public Object execute(ProceedingJoinPoint joinPoint) throws Throwable{ long start = System.currentTimeMillis(); System.out.println("Start : " + joinPoint.toString()); //메소드 명 try{ return joinPoint.proceed(); } finally { long finish = System.currentTimeMillis(); long timeMs = finish - start; System.out.println("End : " + joinPoint.toString() + " " + timeMs + "ms"); } } }
- 스프링 컨테이너는 AOP가 있으면 가짜 스프링 빈(프록시)을 생성 하여 실제 스프링 빈을 호출 하기 전 프록시를 호출한다.
순환 참조 에러
[TimeTraceAop의 AOP 대상을 지정하는 @Around 코드를 보시면, SpringConfig의 timeTraceAop() 메서드도 AOP로 처리하게 됩니다. 그런데 이게 바로 자기 자신인 TimeTraceAop를 생성하는 코드인 것이지요.
그래서 순환참조 문제가 발생합니다. 반면에 컴포넌트 스캔을 사용할 때는 AOP의 대상이 되는 이런 코드 자체가 없기 때문에 문제가 발생하지 않았습니다.
그러면 AOP 설정 클래스를 빈으로 직접 등록할 때는 어떻게 문제를 해결하면 될까요? 바로 위와 같이 AOP 대상에서 SpringConfig를 빼주면 됩니다.]
AOP(TimeTraceAop)를 @Component 로 선언 vs SpringConfig에 @Bean으로 등록 - 인프런
질문 - AOP(TimeTraceAop)를 @Component 로 선언 vs SpringConfig에 @Bean으로 등록 안녕하세요. 김영한 팀장님, AOP(TimeTraceAop)를 @Component로 선언하지 않고 SpringConfig에 @Bean으로 등록할 수 있다고 설명하셨는데
www.inflearn.com
스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - 인프런
스프링 입문자가 예제를 만들어가면서 스프링 웹 애플리케이션 개발 전반을 빠르게 학습할 수 있습니다. 초급 프레임워크 및 라이브러리 웹 개발 서버 개발 Back-End Java Spring MVC Spring Boot 온라인
AOP가 필요한 상황
문제
AOP 적용
시간 측정 AOP 등록
정형화 되지 않고 특수한 기능들은 컴포넌트 스캔 보다 직접 자바 빈으로 등록
SpringConfig
TimeTraceAop
- 스프링 컨테이너는 AOP가 있으면 가짜 스프링 빈(프록시)을 생성 하여 실제 스프링 빈을 호출 하기 전 프록시를 호출한다.
[TimeTraceAop의 AOP 대상을 지정하는 @Around 코드를 보시면, SpringConfig의 timeTraceAop() 메서드도 AOP로 처리하게 됩니다. 그런데 이게 바로 자기 자신인 TimeTraceAop를 생성하는 코드인 것이지요.
그래서 순환참조 문제가 발생합니다. 반면에 컴포넌트 스캔을 사용할 때는 AOP의 대상이 되는 이런 코드 자체가 없기 때문에 문제가 발생하지 않았습니다.
그러면 AOP 설정 클래스를 빈으로 직접 등록할 때는 어떻게 문제를 해결하면 될까요? 바로 위와 같이 AOP 대상에서 SpringConfig를 빼주면 됩니다.]
AOP(TimeTraceAop)를 @Component 로 선언 vs SpringConfig에 @Bean으로 등록 - 인프런
질문 - AOP(TimeTraceAop)를 @Component 로 선언 vs SpringConfig에 @Bean으로 등록 안녕하세요. 김영한 팀장님, AOP(TimeTraceAop)를 @Component로 선언하지 않고 SpringConfig에 @Bean으로 등록할 수 있다고 설명하셨는데
www.inflearn.com
스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - 인프런
스프링 입문자가 예제를 만들어가면서 스프링 웹 애플리케이션 개발 전반을 빠르게 학습할 수 있습니다. 초급 프레임워크 및 라이브러리 웹 개발 서버 개발 Back-End Java Spring MVC Spring Boot 온라인
www.inflearn.com
'기록 > 스프링부트 시작하기' 카테고리의 다른 글