스프링에서 프록시를 적용할 떄 사용하는 3가지 개념
포인트컷 : 어떤 시점에 적용할 것인가에 대한 개념
Pointcut 인터페이스를 기반으로 동작하며 구현하려면 상속받아서 구현하면 된다.
ClassFilter와 MethodMatcher 두가지를 제공하는데
클래스조건, 메소드관련 조건을 걸 수 있다.
@Test
void advisorTest1() {
ServiceInterface target = new ServiceInterfaceImpl();
ProxyFactory proxyFactory = new ProxyFactory(target);
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(Pointcut.TRUE, new TimeAdvice());
proxyFactory.addAdvisor(advisor);
ServiceInterface proxy = (ServiceInterface) proxyFactory.getProxy();
proxy.save();
proxy.find();
}
static class MyPointcut implements Pointcut {
@Override
public ClassFilter getClassFilter() {
return ClassFilter.TRUE;
}
@Override
public MethodMatcher getMethodMatcher() {
return new MyMethodMatcher();
}
}
@Slf4j
static class MyMethodMatcher implements MethodMatcher {
private String matchName = "save";
@Override
public boolean matches(Method method, Class<?> targetClass) {
boolean result = method.getName().equals(matchName);
log.info("포인트컷 호출 method={}, targetClass={}", method.getName(), targetClass);
log.info("포인트컷 결과 result={}", result);
return result;
}
@Override
public boolean isRuntime() {
return false;
}
// isRuntime()가 true인 경우 파라미터가 동적이라고 봄 캐싱을 하지 않는다.
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
return false;
}
}
advice는 프록시가 동작시에 수행하는 내용
MethodInterceptor를 가보면 Interceptor를 상속받고 Advice를 상속받는 것을 확인할 수 있다.
advisor는 포인트컷1 + advice1이다.
최종적으로는 어드바이저를 한번에 사용한다.
스프링에서는 실제적으로 타켓 객체에 대해서 프록시는 1만 생성하고 어드바이저를 여러개 만들어서 동작한다.
@Test
@DisplayName("하나의 프록시, 여러 어드바이저")
void multiAdvisorTest2() {
// client -> proxy1 -> advisor2 -> advisor1 -> target
DefaultPointcutAdvisor advisor1 = new DefaultPointcutAdvisor(Pointcut.TRUE, new Advice1());
DefaultPointcutAdvisor advisor2 = new DefaultPointcutAdvisor(Pointcut.TRUE, new Advice2());
// 프로시1 생성
ServiceInterface target = new ServiceInterfaceImpl();
ProxyFactory proxyFactory1 = new ProxyFactory(target);
proxyFactory1.addAdvisor(advisor2);
proxyFactory1.addAdvisor(advisor1);
ServiceInterface proxy1 = (ServiceInterface) proxyFactory1.getProxy();
proxy1.save();
}
@Slf4j
static class Advice1 implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
log.info("advice1 호출");
return invocation.proceed();
}
}
@Slf4j
static class Advice2 implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
log.info("advice2 호출");
return invocation.proceed();
}
}'Study' 카테고리의 다른 글
| Proxy Factory (0) | 2022.10.05 |
|---|---|
| Cglib dynamic proxy (0) | 2022.10.05 |
| JDK Dynamic Proxy (0) | 2022.09.30 |
| 인터페이스 기반 vs 구체 클래스 기반 프록시 (0) | 2022.09.29 |
| 프록시 패턴 & 데코레이터 패턴 (0) | 2022.09.22 |