Pro Spring 2.5에서 this 표현식에 대한 정의입니다.
the semantics of the this pointcut are such that it would match any method execution on an object whose class matches the specified expression, but how could we match any class in the com package and its subpackages? Therefore, the only allowed syntax is this(class-name),
Pro Spring 2.5에서 target 표현식에 대한 정의 입니다.
Because the target expression defines a pointcut that would match execution of any method on an object whose class matches the specified expression, we cannot use the wildcards.
뭐가 달라 보이나요??? 앞 부분에 어순이 약간 바뀐것 빼고는 도무지 차이를 알 수가 없습니다.
레퍼런스를 보죠.
this - limits matching to join points (the execution of methods when using Spring AOP) where the bean reference (Spring AOP proxy) is an instance of the given type
target - limits matching to join points (the execution of methods when using Spring AOP) where the target object (application object being proxied) is an instance of the given type
레퍼런스는 그나마 좀 차이가 보입니다. this일 때는 프록시 객체고 target 일 때는 프록시를 적용할 타겟 객체가 주체가 됩니다.
즉, this 표현식은 주어진 타입에 해당하는 스프링 AOP Proxy의 조인포인트에 대응하는 표현식이고.. target 표현식은 주어진 타입에 해당하는 타겟 객체의 조인포인트에 대응하는 표현식이라는 것인데..
어차피 프록시 객체의 타입이 곧 타겟 객체의 타입과 동일하기 때문에 결과는 똑같을 것 같은데 말이죠. 차이를 모르겠습니다. 아흐.. 머리야..
마지막으로 AspectJ 문서를 보겠습니다.
this(Type or Id)
Picks out each join point where the currently executing object (the object bound to this) is an instance of Type, or of the type of the identifier Id (which must be bound in the enclosing advice or pointcut definition). Will not match any join points from static contexts.
target(Type or Id)
Picks out each join point where the target object (the object on which a call or field operation is applied to) is an instance of Type, or of the type of the identifier Id (which must be bound in the enclosing advice or pointcut definition). Will not match any calls, gets, or sets of static members.
this는 동적이고 target은 정적으로 타입을 지칭하는 차이밖에 없어보입니다. 흠.. 과연..
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="applicationContext.xml")
public class FooAspectTest {
@Autowired
FooBean fooBean;
@Test
public void isProxy(){
assertTrue(fooBean instanceof Advised);
fooBean.hi();
}
}
@Aspect
public class FooAspect {
@Pointcut("this(org.opensprout.spring.aop.thisandtarget.FooBean)")
public void thisPointcut(){}
@Before("thisPointcut()")
public void say(){
System.out.println("this pointcut executed.");
}
}
스프링 AOP에서는 this를 target으로 고쳐도 똑같이 동작합니다. 콘솔에 메시지가 한 번 출력되죠. 그러나 AJDT로 실행하면, this의 경우 같은 메시지가 세 번 찍히고, target의 경우 같은 메시지가 네 번찍힙니다. 일단 두 번은 클래스 로딩이나 생성자 호출 조인포인트에서 찍혔다고 생각하고, 하나는 테스트에서 hi 호출 할 때 찍힌거고 가장 의아한건 target 표현식일 때의 마지막 한 번.
디버깅을 돌려본 결과 저 테스트에 두 번 들어가던데;; 왜 그런지 몰겠네요. 아~ 미궁이로 구나..
역시 트랜잭션 문제 해결하려면, AOP 를 고려해 보는게 좋겠죠?
저도 최근에 DB Transaction 말고 파일시스템에서 파일 생성, 복사 등등에 관련된
파일 트랜잭션 문제 해결하느라 AspectJ 사용해서
FileTransactionManager 를 만들었습니다.
파일 업로드 하다 실패하면, DB는 Transaction 지원되니,
스프링에서 알아서 rollback 해 주는데, 파일 시스템에 저장된 파일은 해결이 안되서,
일단 AOP로 파일 생성/복사 하는 메소드들만 처리해 주다가
아예 @Transactional 처럼 annotation만 쓰면
알아서 처리해주는 FileTransactionManager를 만들어 버린거죠.
만들면서 또한번 '아! 역시 AspectJ 너무 좋아' 라는걸 느꼈습니다.
넵. 트랜잭션 관리 코드가 서비스 계층으로 올라오면서 부터 지져분해지는 길의 시작이랄까요..그렇다고 DAO에 둘수는 없자나요ㅋ
오홋.. 좋군요. 해당 애노테이션 붙어있는 메서드에 포인트컷 걸고 예외 발생했을 때 생성된 파일을 청소해주는 어드바이스 적용하셨나보군요.
근데 ApsectJ는 조금 귀찮지 않으세요? 위버나 ajc를 사용해야 할텐데요. 하긴 ajc를 메이븐 빌드로 돌리면 별로 귀찮지 않을수도..
네, 그렇게 되는거죠.

거기에 nested transactions 관련된 부분 조금 신경쓴거 정도겠군요.
트랜잭션 걸린 메소드 안에서 실행되는 다른 메소드에 트랜잭션이 겹겹이 걸렸다고 이미 지운 파일을 또 지우려고 하면 안돼잖아요. 거기다가 트랜잭션 전체가 끝날때까지 생성된 파일 정보를 가지고 있다가
모든 트랜잭션이 전부 마무리 되었을때, 관리하에 있던 파일 정보 다 날리는거랑요.
가끔 privileged aspect 를 쓸일이 있어서
ajc 를 쓰고 있습니다만, 직접 컴파일 하는게 아니고
Eclipse에서는 AJDT 와 m2eclipse 를 써서 별 불편없구요.
빌드시에는 maven으로 aspectj-maven-plugin 써서 하구요.
그래서 크게 귀찮은거 없는데...
사실 불편이 없어야 하는데 하나가 좀...
가끔 스프링의 @Transactional 적용한 메소드에
weaving이 잘 안되는 경우가 있더군요.
아무래도 aspectLibrary 적용하는 부분때문에 그런거 같습니다만.
실험좀 해보니까, m2eclipse에서 full-build 를 해야
이게 정상적으로 위빙이 되는데...
m2eclipse와 AJDT eclipse-maven-plugin 중에
어디가 문제인지는 모르겠지만, 아무튼 이게 가끔 제대로 안되더군요.
수동 clean 빌드를 하면 full-build를 수행해서 정상적으로 되구요.
해결하려고 이거저거 다 시도 해봤는데, clean말고 더 편한 해결책을
못 찾았습니다. ㅠ_ㅠ 그냥 m2eclipse가 AJDT 이용해서
컴파일 하면서 full-build 하면 될것 같은데... 이녀석이 말을 안 듣네요.
아무튼 그래서 코딩하다가 실행해 보기 전에 clean을 해줘야 하는게
좀 불편합니다. 그래서 이거 단축기 걸어놓고 쓰고 있어요.
아... 그리고 그래서 Eclipse 버리기가 힘드네요.
NetBeans 나 IntelliJ IDEA 다 써봤는데,
이거 세세하게 제 마음대로 옵션을 바꾸려니 Eclipse 만큼 편한게 없네요.
저는 foramming 부터 해서 단축키등등 이거저거 제가 편하게 쓸수 있게
설정해서 쓰기 때문에 NetBeans 처음 사용해보고 불편해서 바로 삭제...ㅡ_ㅡ;
암튼, 사실 생각보다 크게는 불편하지는 않구요.
코딩 조금하고 실행해보고 이러지 않고 한참 하고나서 실행해 보니까요.
(빌드전까지 보통 한번만 실행...^^; )
실행전에 clean 한번 해주는걸로 해결하고 있습니다.
중간에 자잘한거 테스트는 테스트 코드가 해주구요.
아 근데, 쓰다보니 하나 떠오르는게 있네요. 아무래도 AJDT가 이해하게
따로 aspectPath를 설정해 줘야 할것 같기도하고,
이게 pom.xml에 되어 있긴 한데... 아무튼 지금은 잘 쓰고 있으니
시간나면 한번 실험해 봐야겠네요.
흠.. 인텔리J도 얼마든지 단축키를 맘대로 바꿔서 사용할 수 있어요. 요즘은 둘다 번갈아 가면서 쓰고 있긴 한데 그래도 인텔리J를 더 자주 쓰게 되네요.
궁극적으로는 스프링 AOP에서 AspectJ로 넘어가면 좋긴하겠는데(프록시 내부 호출이나 런타임 오버헤드를 해결할 수 있으니) 기능이 너무 강력하단게 어떨땐 흠인것 같기도 하고.. AspectJ까지 사용할만큼 AOP를 즐겨 쓰진 못해서 걍 스프링 AOP로 만족하고 있어요 ㅋㅋ