AOP (Aspect-Oriented Programming) : 관점 지향 프로그래밍
- 흩어진 Aspect들을 모아서 모듈화 하는 기법이다.
- 여러 오브젝트에 나타나는 "공통적인 부가 기능"을 모듈화하여 "재사용"하는 기법이다.
주로 어떤경우에 사용할까요?
- 모든 메소드의 호출 시간을 측정하고 싶다면?
- 공통 관심사항(cross-cutting-concern) vs 핵심 관심사항(core concern)
- 회원 가입 시간, 회원 조회 시간을 측정하고 싶다면?
코드의 중복 발생을 해결하기 위해 나온것이 AOP 입니다.
AOP는 어떻게 등록하나요?
1. 컴포넌트 스캔 (@Component)
2. 빈에 직접등록 (권장)
아래와 같이 셋팅합니다.
1. build.gradle에 의존성 추가
2. TimeTraceAop 만들기 (@Component 선언하면 3번 생략)
package hello.core.aop;
import org.springframework.stereotype.Component;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
//@Component 1번 방법
@Aspect
public class TimeTraceAop {
@Around("execution(* hello.core..*(..))")
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");
}
}
}
* @Around 어노테이션은 타겟 메서드를 감싸서 특정 Advice를 실행한다는 의미이다. 위 코드의 Advice는 타겟 메서드가 실행된 시간을 측정하기 위한 로직을 구현하였다. 추가적으로 execution(* hello.core..*(..))가 의미하는 바는 hello.core 아래의 패키지 경로의 객체의 모든 메서드에 이 Aspect를 적용하겠다는 의미다.
3. Bean 객체 등록
package hello.core;
import hello.core.aop.TimeTraceAop;
import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import hello.core.member.MemberRepository;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 구현 객체 생성 및 연결
@Configuration
public class AppConfig {
// 생성자를 통해서 주입(연결) 즉, 인젝션 해준다. (DIP 완성)
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public DiscountPolicy discountPolicy() {
return new RateDiscountPolicy();
}
// AOP 적용
@Bean
public TimeTraceAop timeTraceAop() {
return new TimeTraceAop();
}
}
AOP 해결 및 장점 :
- 회원가입, 회원 조회등 핵심 관심사항과 시간을 측정하는 공통 관심 사항을 분리한다.
- 시간을 측정하는 로직을 별도의 공통 로직으로 만들었다.
- 핵심 관심 사항을 깔끔하게 유지할 수 있다.
- 변경이 필요하면 이 로직만 변경하면 된다.
- 원하는 적용 대상을 선택할 수 있다.
어떤 부가기능을? 언제? 사용할까요????
Advice : 어떤 부가기능을 언제 사용할지에 대한 정의
어디에?
Joinpoint : 어드바이스가 적용될 수 있는 위치 (메서드 호출, 필드 값 변경)
- 메서드 호출할때 (스프링AOP는 프록시기반) 적용됨.
- 변수에 접근할 때
- 객체를 초기화할 때
- 객체에 접근할 때
그 이외 설명
Pointcut : Advice를 적용할 Joinpoint를 선별하는 작업
Tartget : 부가 기능이 적용될 대상 Aspect를 적용하는 곳
Aspect : 여러 객체에 적용되는 기능 (트랜잭션이나 보안에 사용 됨)
AOP는 어디에 사용될까요?
1. 성능 검사
2. 트랜잭션 처리
3. 로깅
이 밖에도 @Around 외에 타겟 메서드의 Aspect 실행 시점을 지정할 수 있는 어노테이션이 있다.
- @Before (이전) : 어드바이스 타겟 메소드가 호출되기 전에 어드바이스 기능을 수행
- @After (이후) : 타겟 메소드의 결과에 관계없이(즉 성공, 예외 관계없이) 타겟 메소드가 완료 되면 어드바이스 기능을 수행
- @AfterReturning (정상적 반환 이후)타겟 메소드가 성공적으로 결과값을 반환 후에 어드바이스 기능을 수행
- @AfterThrowing (예외 발생 이후) : 타겟 메소드가 수행 중 예외를 던지게 되면 어드바이스 기능을 수행
- @Around (메소드 실행 전후) : 어드바이스가 타겟 메소드를 감싸서 타겟 메소드 호출전과 후에 어드바이스 기능을 수행
출처 : 김영한의 스프링
출처 : 최범균의 스프링
출처: https://engkimbs.tistory.com/746 [새로비]
'SPRING > 기본 상식' 카테고리의 다른 글
[SPRING] 조회 빈이 2개 이상 일 때 해결 방법 (0) | 2021.04.27 |
---|---|
[SPRING] @Bean vs @Component (0) | 2021.04.14 |
[SPRING] 스프링 컨테이너 (싱글톤 패턴 개선) (0) | 2021.04.13 |
[SPRING] EJB(Enterprise Java Bean) (0) | 2021.04.13 |
[SPRING] Spring WebFlux 리액티브 프로그래밍 개념 (0) | 2021.04.13 |