Proxy
는 대신이라는 의미이며 다른 무언가와 이어지는 인터페이스의 역할을 하는 패턴입니다. 한마디로 무언가를 대신해주는 대리자
입니다. 1 ) 인터페이스
public interface Payment {
void cashPay(int amount);
void creditPay(int amount);
}
2 ) RealSubject
@Service
public class PaymentService implements Payment{
@Override
public void cashPay(int amount) {
System.out.println("cashPay : " + amount);
}
@Override
public void creditPay(int amount) {
System.out.println("creditPay : " + amount);
}
}
3 ) Proxy
@Primary // client에 payment를 호출하면 ProxyPaymentService가 먼저 호출된다.
@Service
public class ProxyPaymentService implements Payment {
@Autowired
PaymentService paymentService;
@Override
public void cashPay(int amount) {
long begin = System.currentTimeMillis(); // 기능 1
paymentService.cashPay(1000); // 원래 객체에 위임
System.out.println(System.currentTimeMillis() - begin); // 기능 2
}
@Override
public void creditPay(int amount) {
long begin = System.currentTimeMillis(); // 기능 1
paymentService.creditPay(1000); // 원래 객체에 위임
System.out.println(System.currentTimeMillis() - begin); // 기능 2
}
}
AOP란 Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 한다. 여기서 Aspect(관점)이란 흩어진 관심사들을 하나로 모듈화 한 것을 의미한다.
객체 지항 프로그래밍(OOP)에서는 주요 관심사에 따라 클래스를 분할한다. 이 클래스들은 보통 SRP(Single Responsibility Principle)에 따라 하나의 책임만을 갖게 설계된다. 하지만 클래스를 설계하다보면 로깅, 보안, 트랜잭션 등 여러 클래스에서 공통적으로 사용하는 부가 기능들이 생긴다. 이들은 주요 비즈니스 로직은 아니지만, 반복적으로 여러 곳에서 쓰이는 데 이를 흩어진 관심사(Cross Cutting Concerns)라고 한다.
@Component
@Aspect
@EnableAspectJAutoProxy
public class BasicAspect {
@Around("* basic.PaymentService")
public Object logPref(ProceedingJoinPoint pjp) throws Throwable {
long begin = System.currentTimeMillis();
Object proceed = pjp.proceed();
System.out.println(System.currentTimeMillis() - begin);
return proceed;
}
}
Around → pointcut으로 클라이언트의 호출을 가로채서 비즈니스 메소드 호출에 책임을 감당한다. 그 때 around Advice 메소드가 비즈니스 메소드의 정보를 가지고 있어야 하는데 그것을 ProceedingJoinPoint 객체라고 한다.
@Documented
@Target(ElementType.METHOD) // target -> method
@Retention(RetentionPolicy.CLASS) // .class 파일까지 유지
@Retention(RetentionPolicy.SOURCE) // 컴파일 시 사라짐
public @interface PerfLogging {
}
@Component
@Aspect
@EnableAspectJAutoProxy
public class BasicAspect {
@Around("@annotation(PerfLogging")
public Object logPref(ProceedingJoinPoint pjp) throws Throwable {
long begin = System.currentTimeMillis();
Object proceed = pjp.proceed();
System.out.println(System.currentTimeMillis() - begin);
return proceed;
}
}
김영한님의 스프링 고급 AOP → 정리글
Spring에서 지원하는 AOP Proxy ( CGLIB , JDK Dynamic Proxy ) → 정리글