2015년 5월 21일 목요일

Java Dynamic Proxy vs CGLib Proxy vs AspectJ Weaving #4

3. AspectJ Weaving
AspectJ는 AOP(Aspect Oriented Programming)을 가능케 해주는 Java 라이브러리 입니다.
실제로 현업에서  AspectJ를 많이 쓰고 있는지는 잘 모르겠지만, Spring AOP를 이해하는데 도움이 될 것 같습니다. 동작 원리는 비슷하니까요.
AspectJ는 사실 Proxy와는 다르지만, 기존 코드를 수정하지 않고 추가적인 기능을 만들 수 있다는 점에서는 거의 비슷하다고 볼 수 있습니다.

예제를 한번 보겠습니다. 다음과 같이 간단한 문자열을 출력하는 Target.test() 메쏘드가 있습니다.
package aspectj;

public class Target { 
 public void test() {
  System.out.println("Target.test()");
 }

}

위의 test() 메쏘드가 호출될 때마다, 또다른 문자열을 출력하고 싶을 때 다음과 같은 @Aspect를 추가할 수 있습니다.
package aspectj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class LoggingAspect {
 
 @Before("execution (* aspectj.Target.test*(..))")
 public void advice(JoinPoint joinPoint) {
  System.out.printf("LoggingAspect.advice() called on %s %n", joinPoint);
 }
}

@Before 어노테이션은 target 메쏘드가 실행되기 전에 실행됩니다. execution 뒤에 있는 문자열의 의미는

* : 모든 access modifier (public, private, protected)
aspectj.Target.test*: aspectj.Target클래스 내의  이름이 test로 시작하는 모든 메쏘드
(..): 모든 매개변수에 대해서

위의 advice() 메쏘드는 aspectj.Target 클래스에서 이름이 test로 시작하는 모든 메쏘드 (public, private, proteced 상관없이)가 실행되기 전에 항상 실행됩니다.

아래 링크에서 소스를 받아서 메이븐을 실행하면 다음의 결과를 볼 수 있습니다.

> mvn clean test

Running aspectj.LogginAspectTest
LoggingAspect.advice() called on execution(void aspectj.Target.test()) 
Target.test()
LoggingAspect.advice() called on execution(void aspectj.Target.test2()) 
Target.test2()

AspectJ를 사용함에 있어 한가지 주의해야 할 것이 있는데, aspectj-maven-plugin이 compiler-maven-plugin과 호환되지 않는 부분이 있습니다. 이것 때문에 원인을 찾기에 고생을 좀 했네요. complianceLevel을 1.6으로 해주어야 정상적으로 동작합니다.

<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<complianceLevel>1.6</complianceLevel>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>



전체 소스 코드는 https://github.com/jinwooe/dynamic-proxy-cglib-aspectj-example 에서 받을 수 있습니다

참고 사이트
http://java.dzone.com/articles/power-proxies-java
http://denis-zhdanov.blogspot.kr/2009/08/weaving-with-aspectj.html

댓글 없음:

댓글 쓰기