AOP와 트랜잭션
프록시(Proxy)패턴 방식
- 외부에서 특정한 객체(target)를 호출하면, 실제 객체를 감사고 있는 바깥쪽 객체(Proxy)를 통해서 호출이 전달된다.
Proxy객체는 AOP의 기능이 적용된 상태에서 호출을 받아 사용되고, 실제 객체와 동일한 타입을 자동으로 생성할 수 있기 때문에 외부에서는 실제 객체와 동일한 타입으로 호출할 수 있다.
- 프록시는 일반적인 의미에서는 직접 호출하는 방식이 아니라 간접적인 호출을 하는 것을 의미한다.
즉 원래 객체인 target을 호출할 때 외부에서 직접 target을 호출하는 것이 아니라, Advice가 적용된 Proxy 객체를 통해서 호출한다는 것을 의미한다.
Aspect
- 공통 관심사에 대한 추상적인 명칭. 예를 들어 로깅이나 보안, 트랜잭션과 같은 기능자체에 대한 용어
Advice
- 실제로 기능을 구현한 객체
- 실제 적용시키고 싶은 코드 자체, 개발자가 만드는 것은 Aspect가 아닌 클래스를 제작하고 @Advice를 적용하는 것임.
예를 들어 로그 출력 기능
target
- 대상 메소드를 가지는 객체
- 실제 메소드를 비즈니스 로직을 수행하는 객체를 의미, 용어 그대로 Aspect를 적용해야 하는 대상 객체를 의미함
Join points
- 공통 관심사를 적용할 수 있는 대상. Spring AOP에서는 각 객체의 메소드가 이에 해당
- 작성된 Advice가 확약할 수 있는 위치를 의미, 예를 들어 BoardService에서 등록, 수정, 삭제만을 골라서 Advice를 적용할 수 있는데, 이때 BoardSerivice의 모든 메소드는 JoinPoint가 됨
Pointcuts
- 여러 메소드 중 실제 Advice가 적용될 대상 메소드
- 여러 Join Points 중에서 Advice를 적용할 대상을 선택하는 정보, 이를 통해서 특정 메소드는 Advice가 적용된 형태로 동작함
Proxy
- Advice가 적용되었을 때 만들어지는 객체
introduction
- target에는 없는 새로운 메소드나 인스턴스 변수를 추가하는 기능
Weaving
- Advice와 target이 결합되어서 프록시 객체를 만드는 과정
Advice의 종류
Before Advice - target의 메소드 호출 전에 적용
After returning - target의 메소드 호출 이후에 적용
After throwing - targer의 예외 발생 후 적용
After - targer의 예외 발생 후 예외의 발생에 관계없이 적용
Around - targer의 메소드 호출 이전과 이후 모두 적용(가장 광범위하게 사용됨)
AOP적용을 위해 추가해야 하는 라이브러리와 설정
<properties>
<java-version>1.8</java-version>
<org.springframework-version>4.3.8.RELEASE</org.springframework-version>
<org.aspectj-version>1.8.9</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<!-- AOP -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
스프링에서 AOP를 처리하기 위해서는 Proxy 객체를 생성할 필요가 있다.
Proxy 객체를 만드는 방법은 크게 JDK의 InvocationHandler를 이용하는 Dynamic Proxy 방식과 CGLIB를 이용하는 방식이 사용된다.
이를 위해 AspectJ 언어의 문법을 이용하기에 라이브러리 추가가 필요하다.
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
root-context.xml의 설정
XML을 이용하는 설정은 'servlet-context.xml'이나 'root-context.xml'에서 사용하는 XML 네임스페이스가 필요하므로 설정 메뉴를 이용해서 'aop'와 'tx' 네임스페이스를 추가해야 한다.
root-context.xml에서 AOP의 설정을 통한 자동적인 Proxy 객체 생성을 위해서 다음과 같은 설정을 미리 추가한다.