스프링은 일관된 방법으로 프록시를 만들 수 있게 도와주는 추상 레이어를 제공한다
생성된 프록시는 스프링 빈으로 등록되어야 하며, 스프링은 프록시 객체를 생성해주는 기술을 추상화한 팩토리빈 ProxyFactoryBean을 제공해준다
MethodInterceptor 인터페이스를 구현해서 만든다MethodInterceptor의 invoke() 는 ProxyFactoryBean으로부터 타깃 객체에 대한 정보를 함께 제공받기 떄문에, 타깃 객체에 상관없이 독립적으로 생성되어질 수 있다MethodInterceptor 객체는 타깃이 다른 여러 프록시에서 함께 사용할 수 있고, 싱글톤 빈으로 등록 가능하다MethodInvocation의 동작MethodInvocation은 일종의 콜백 객체로, proceed()를 실행하면 타깃 객체의 메소드를 내부적으로 실행해주는 기능을 가지고 있다.MethodInvocation 구현 클래스는 일종의 공유 가능한 템플릿처럼 동작한다.MethodInvocation의 동작 때문에MethodInterceptor는 부가 기능을 제공하는 데만 집중할 수 있다.ProxyFactoryBean에 MethodInterceptor 설정 시, addAdvice()를 사용해서 여러 MethodInterceptor를 동시에 추가할 수 있다.ProxyFactoryBean 하나로 여러 부가 기능을 제공하는 프록시를 생성할 수 있다.MethodInterceptor는 Advice 인터페이스를 상속하고 있는 서브 페이스MethodInterceptor 타입의 어드바이스를 호출한다.MethodInvocation 객체: 콜백ProxyFactoryBean 적용MethodInterceptor라는 Advice 서브 인터페이스를 구현한 TransactionAdvice 작성MethodInvocation 타입의 콜백을 이용해서 번거로운 타깃 메서드 호출 작업을 대부분 제거InvocationTargetException으로 래핑되지 않고 그대로 캐치해서 처리public class TransactionAdvice implements MethodInterceptors{ // 스프링의 인터페이스 구현
// 중략
// 타깃을 호출하는 기능을 가진 콜백 객체(MehotdInvocation 타입의 객체)를 프록시로부터 받음
public Object invoke(MehotdInvocation invocation)throws Throwable{
// 중략
try{
Object ret = invocation.proceed(); // 콜백을 호출해서 타깃 메서드 실행 가능
} catch (RuntimeException e){ // 예외가 래핑되지 않고 타깃에서 보낸 그대로 전달된다
// 생략
DefaultAdvisorAutoProxyCreator는 어드바이저를 이용한 자동 프록시 생성기로, 스프링은 빈 후처리기가 빈으로 등록되어 있으면 빈 객체가 생성될 때마다 빈 후처리기에 보내서 후처리 작업을 요청한다.DefaultAdvisorAutoProxyCreator 빈 후처리기가 등록되어 있으면, 스프링은 빈 객체 생성마다 후 처리기에 빈을 보낸다.DefaultAdvisorAutoProxyCreator는 포인트컷을 이용해 전달받은 빈이 프록시 적용 대상인지를 확인한다.ClassFilter와 MethodMatcher 두 가지를 돌려주는 메서드를 가지고 있다ProxyFactoryBean에서는 굳이 클래스 레벨의 필터는 필요 없었지만, DefaultAdvisorAutoProxyCreator는 클래스와 메서드 선정 알고리즘을 모두 갖고 있는 포인트컷과 어드바이스가 결합되어 있는 어드바이저가 필요하다.public class NameMatchClassMethodPointcut extends NameMatchMethodPointcut{
public void setMappedClassName(String mappedClassName){
this.setClassFilger(new SimpleClassFilter(mappedClassName));
// 모든 클래스를 다 허용하던 디폴트 클래스 필터를
// 프로퍼티로 받은 클래스 이름을 이용해서 필터를 만들어 덮어씌움
// 생략
AspectJ 프레임 워크의 일부 문법을 확장한 표현식으로, AspectJExpressionPointcut 클래스를 사용해서 적용 가능하다.execution()execution([접근제한자 패턴] 타입패턴 [타입패턴.]이름패턴 (타입패턴 | "..", ...)[throws 예외패턴])
| 구성 요소 | 설명 | 예시 |
|---|---|---|
| 접근제한자 패턴 | public, private 등 | public |
| 타입패턴 | 반환 타입 (와일드카드 * 가능) | *, String, void |
| 타입패턴. | 메서드가 속한 클래스의 경로 | com.example.service.*. |
| 이름패턴 | 메서드 이름 (와일드카드 가능) | get*, *Service, save |
| (타입패턴, ...) | 매개변수 타입 (0개 이상) | (int, String), (..) |
| throws 예외패턴 | 던질 수 있는 예외 타입 | throws IOException |