Whiteship's Note


Toby's 스프링 AOP 마무리



지금은 스프링 AOP를 넘어서 스프링 활용 부분을 읽고 있는데 기억에서 떠나기 전에 정리해둬야겠다.

 AOP 챕터가 다소 크다는 느낌을 받았다. 스프링 AOP 기능 뿐 아니라 트랜잭션에 관한 설명도 상당 부분이 나온다. 하지만 스프링 트랜잭션을 이해하려면 스프링 AOP에 대한 이해가 필수적이고 스프링 AOP를 이해하기 위한 좋은 예로 스프링 트랜잭션 만큰 좋은 것도 없다고 생각이 든다. 따라서 스프링 AOP를 설명한 굉장한 분량만큼이나 그 노고를 느낄 수 있었다. 특히 중간 중간 텍스트로 인해 지칠 수 있는 독자들을 위한 그림들은 상당히 단순 명료하면서도 배려적이다.

그 중에서 가장 눈길을 끈 곳은 포인트컷 테스트였다. 정말 대박이었다. 예전에 읽었을 때에도 감명을 받고 사실 그 내용을 바탕으로 포인트컷 표현식 테스트에 대한 블로깅까지 했던적이 있다. AOP를 사용할 때 항상 고민하던 부분이었다. 도대체 이 포인트컷이 어디에 적용이 되는건지 확실하게 알 수 없을까... 이클립스나 인텔리J 도움 없이 조인포인트를 확인할 수 있는 아주 간단한 방법이 있다는 것을 보고는 새삼 놀랐다. 내가 너무 모른다는 사실도 한몫했다.

또한 execution 포인트컷에서 사용하는 표현식을 분석한 표역시 대단하다는 생각밖에 들지 않는다. AOP 용어도 이해하고 대강의 사용법까지 익히더라도 항상 막막한 부분은 바로 표현식 작성이었다. 지금 읽은 부분에서는 아직 args나 this, type같은 건 등장하지 않았지만 아마 2부에서 더 자세하게 다룰 것 같다.

AOP 용어 정의를 거의 맨 뒤에서 설명하는 이럭 획기적인 방식으로도 AOP를 더 쉽고 알차게 학습 할 수 있다는 사실에 여러분도 놀랐것이다.  



top


Toby's 스프링 AOP 등장 배경을 읽으며...



이번 기회에 스프링 AOP를 새로운 방식으로 학습하고 있다. 지금은 일단 스프링 AOP의 용어나 기능보다는 그 근본이 되는 ProxyFactoryBean의 유용함, 등장 배경을 이해하는데 초점을 맞추고 있다. 굉장히 중요한 부분이지만 도무지 레퍼런스에서는 이런 내용을 습득할 수 없었다. 빨간책(몇번째 시리즈인지는 까먹음. with Spring이던가..)에서는 언급이 되어 있지만 왠지 어렵고 잘 머리에 들어오지 않는다.

그 등장 배경을 이해하는 것은 결코 쉽지 않다. 그만큼 간단한 절차가 아니기 때문이다. 조금 길다 싶을 정도로 여러 단계의 정제 과정을 걸치게 된다. 그 과정 하나 하나에 문제, 해결책, 장점, 단점 또 그 단점을 극복하는 해결책 그 결과의 장점과 단점. 다시 또 그 단점을 극복하는 .. 이런식으로 꼬리에 꼬리를 물고 가다가 결국에 스프링 AOP의 핵심 요소들이 등장하게 된다. 

마침내 어드바이스, 포인트컷, 어드바이져, 포인트컷 표현식등 AOP 용어가 들려오더라도 전혀 당황스럽지 않다. 그 용어들의 느낌과 개념이 자연스럽게 이해된다. 어드바이스는 머다. 포인트컷은 머다. 라는 식으로 AOP 무식하게 학습했던 과거가 부끄럽게 느껴진다. 이런 학습방법으로 접근했다면 천천히 가는 것처럼 느껴졌겠지만 오히려 더 확실하게 개념을 익힐 수 있었을텐데 라는 생각이 많이 들었다.

이 부분에서 꼭 집중해서 살펴봐야 할 부분이 있다면 BeanPostProcessor가 언급된 부분이다. 그 부분을 자세히 읽으면 AOP 적용시 흔히 실수하는 상황을 잘 캐치할 수 있을 것이다. 보통 빈 설정을 잘못해서 AOP가 적용되지 않는 경우가 많은데 왜 그런지 그 이유와 원인을 이해할 수 있을 것이다.

이제 본격적으로 스프링 AOP에 대한 내용을 읽어야 하는데 시간이 늦어서 집에가서 봐야겠다..
그 작업을 target으로 집안청소 Advice와 퇴근 후 일정 Pointcut을 조합한 Advisor를 감지하여 프록시를 만들어 주는 DefaultAdvisorAutoProxyCreator를 설정해야겠다.
top


[스프링 3.0 @MVC] 컨트롤러에 스프링 AOP가 적용되지 않는다는건 이제 거짓말

모하니?/Coding : 2010.02.17 14:49


@MVC를 사용하면 좋은 점 중 하나가 스프링 AOP 적용이 쉽다는 겁니다. 아직도 여러 이유로 이전의 Controller 계층 구조를 이용해서 개발하시는 분들이 많겠지만 @MVC를 사용하시는 분들은 이점을 꼭 알고 계셔야 합니다. 스프링 @MVC도 이제 스프링 AOP가 아주 잘 먹힙니다.

@Controller
public class TestController {

    @RequestMapping("/test")
    @Transactional
    public void test() {
        System.out.println("hi!!!!!!!!!!!!!!!!!!!!!!");
    }

}

하지만 그렇다고 해서 이런 코드를 작성해 달라는 것은 아닙니다. 절대로.. 네버..

어찌됐든 위와 같은 코드도 동작하게 되어있는데 경우에 따라서는 안 될 수도 있습니다. 그런 경우는 스프링 트랜잭션이나 스프링 시큐리티 애노테이션에 문제가 있는것이 아니라 빈설정과 관련이 있을 수가 있으니 빈 설정을 잘 보셔야 합니다.

만약 위와 같은 경우라면.. @Controller 빈이 만들어지는 ApplicationContext와 tx:annotation 머시기가 등록되는 ApplicationContext가 같은지 확인해봐야 합니다.

정말,, 굳이.. 컨트롤러에 AOP를 적용해야 한다면 http://toby.epril.com/?p=934 이 글따라서 DS가 만드는 WebAC 하나로 모두 통합하는 것도 좋겠습니다.
top


ProxyFactoryBean을 이용한 초간단 AOP 구현

모하니?/Coding : 2009.12.16 16:01


스프링 AOP가 어렵다고 생각하시는 분들은 저 클래스를 사용하는 방법부터 익히시면 도움이 될 것 같습니다.
아주 간략하게 ProxyFactoryBean을 사용해서 AOP를 적용해 보겠습니다.

AOP는 OOP 같은 프로그래밍 기법이지 무슨 기술이 아닙니다. 따라서 이 글에서 구현하는 내용은 AOP 적용 방법 중 하나라고 생각하시면 됩니다.

    interface Service {
        public void hi();
        public void hi2();
    }

이런 인터페이스가 있고

    class ServiceImpl implements Service {
        public void hi(){
            System.out.println("my business");
        }

        @Override
        public void hi2() {
            System.out.println("my2");
        }
    }

이런 구현체가 있을 때. hi() 호출 전 후에만 메시지를 출력하고 hi2()는 걍 저대로 출력하고 싶다면 ...  우선 해당 작업을 수행할 MethodIterceptor 인터페이스의 구현체를 만듭니다.

    class ServiceLoggingAdvice implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("before hi");
            invocation.proceed();
            System.out.println("after hi");
            return null; 
        }
    }

그리고 hi()와 hi2()를 선별해줄 NameMatchMethodPointcut을 만듭니다.

    class ServiceLoggingPointcur extends NameMatchMethodPointcut {

        ServiceLoggingPointcur() {
            setMappedName("hi");
        }
    }

이제 마지막으로 ProxyFactoryBean으로 위에서 만들었던 타겟(Service 구현체), 어드바이스(MethodInterceptor 구현체), 포인트컷(NameMatchMethodPointcut 구현체)을 ProxyFactoryBean에 설정 해주면 끝!

    Service service;
    ProxyFactoryBean proxyFactoryBean;

    @Before
    public void setUp(){
        proxyFactoryBean = new ProxyFactoryBean();
        proxyFactoryBean.setTarget(new ServiceImpl());
        proxyFactoryBean.addAdvisor(new DefaultPointcutAdvisor(
                new ServiceLoggingPointcur(),
                new ServiceLoggingAdvice()));
    }

    @Test
    public void logging(){
        Service service = (Service) proxyFactoryBean.getObject();
        service.hi();
        service.hi2();
    }

이렇게 하면 콘솔에


요런식으로 출력됩니다.

자세한 내용은 언젠간 출간될 Toby님의 스프링 책을 참조하세요.




top


프로 스프링 2.5 6장 저자와 번역 합의 메일



봄싹스터디에서 베타리딩 중인 프로 스프링 2.5 6장 AOP 관련 내용 중에 이상한 부분이 있다는 글이 올라온적이 있습니다. 성윤님이 올린 글 @Aspect는 누구의 것?이라는 글인데 저 부분을 번역한 것이 바로 접니다. 번역하면서도 저 부분이 뭔가 맘에 걸렸지만 일단은 번역 자체가 급해서 걍 넘어갔었는데 다행히도 베타리딩에서 잘 걸렸네요.

몇 일 미루다가 오늘 아침 저자에게 메일을 보냈습니다.

사용자 삽입 이미지

대충 @AspectJ 애스팩트가 AspectJ에 의존하는데 왜 의존하지 않는다고 썼느냐.. 라고 보냈습니다. 그랬더니 답장이 왔는데..

사용자 삽입 이미지

음.. 이건 걍 읽어보시면 좋은 내용입니다. 본래는 어쩌구 저쩌구 하면서 좀 장황하게 얘기를 해주네요. 중요한건 ApsectJ 라이브러리를 참조하기는 하지만 애노테이션을 떄문에 참조하는 것이지 스프링 AOP를 사용할 때는 AspectJ의 compile-time weaving 같은 컴포넌트를 사용하진 않는다는 겁니다. 그런 뜻으로 AspectJ에 의존하지 않는다고 한거라는거죠.

하지만 너무 애매하자나요. 그래서 다시 메일을 보냈습니다.

사용자 삽입 이미지

애매하니까 AspectJ 라이브러리에서 애노테이션만 사용하고 다른 것들은 사용하지 않는다는 식으로 번역하겠다고 보냈습니다.

사용자 삽입 이미지

귿~ 잘 해결됐네요. 그렇게 하랍니다. 번역서에서는 좀 더 분명하게 적어드리겠습니다.


top


[KSUG] 스프링 AOP 선택, 활용, 이슈 - 스크린캐스팅

Spring/KSUG : 2008.11.11 08:56




위 링크에서 동영상 링크를 사용하여 mov 파일을 다운 받으시거나, 퀵 타임 플레이어가 설치되어 있다면, 웹에서 바로 보실 수도 있습니다.

발표를 하고 2주 정도 지난 다음 녹화를 한 건데, 스크린캐스팅을 좀 짧게 찍고 싶어서 총 다섯 개로 나눠서 한 편당 10~15 내외로 찍었습니다. KSUG 블로그를 통해서 한 주에 한 편식 올리겠습니다. 쉬는 시간 짬짬히 구경해 주세요. :)

이번에 올린 동영상은 AOP에 대한 내용인데, AOP 자체에 대해서는 깊게 알지 못하기 때문에, 제가 아는 한도 내에서만 살짝 살펴봤습니다. 따라서 내용이 다소 수박겉할기식으로 느껴질 수도 있는데요. 첫 번째 동영상의 목적은 AOP에 대해 자세히 설명 드리는 것이 아니라 AOP라는 개념을 프로젝트에 도입하면 어떤 도움을 받을 수 있는지 좀 더 현실적인(코드를 통해서) 감을 잡게 해드리는 것이 목적이기 때문에 그다지 AOP 개념이나 역사에 대해 자세히 다루진 않았습니다. 가볍게 보실 수 있겠죠.ㅋ

어느새 점심 시간이네요. 식사 맛나게 하세요.

updated 2008/11/11

이번에는 스프링 AOP에 대한 주제로, 코딩으로 Proxy 만드는 방법, 스프링 API 사용 방법, XML 스키마 사용 방법, @AspectJ 사용 방법, AspectJ 연동 방법까지 살펴봅니다.

next 2008/11/18
top


스프링 AOP에서 this와 target 포인트컷 표현식 구분 하시는 분?

Spring/Chapter 7 : 2008.11.05 11:42


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 표현식일 때의 마지막 한 번.

디버깅을 돌려본 결과 저 테스트에 두 번 들어가던데;; 왜 그런지 몰겠네요. 아~ 미궁이로 구나..
top


스프링 AOP 선택, 활용, 이슈 - 발표자료 & 소스코드

Spring/KSUG : 2008.10.14 14:49


원래 계획대로면 스크린캐스팅도 제공해야 하는데, 제가 이번 주에는 여유가 없을 것 같아서 일단 발표자료만 올립니다. KSUG에서 별다른 연락이 없기 때문에 일단 제 블로그에 올리죠. 나중에 KSUG에서 일괄적으로 정리해서 발표 자료 묶음을 올리면 좋겠네요.


방명록에 보니 소스코드 요청도 있어서, 같이 올려둡니다. 메이븐 프로젝트인데, 몇몇 라이브러리는 메이븐 중앙 저장소에서 받지 못할 수도 있습니다. 그럴 때는, OSAF 메이븐 저장소를 원격 저장소로 등록해서 사용하시면 됩니다. OSAF 메이븐 저장소 주소는 다음과 같습니다.

http://www.opensprout.org:8082/nexus/content/groups/public/


top


개발에 필요한 AOP 뭐가 있을까?

AOP : 2008.10.06 17:22


1. 간단한 메소드 성능 검사

 개발 도중 특히 DB에 다량의 데이터를 넣고 빼는 등의 배치 작업에 대해서 시간을 측정해보고 쿼리를 개선하는 작업은 매우 의미가 있을 겁니다. 그럴 때 귀찮게 매번 해당 메소드 처음과 끝에 System.currentTimeMillis();를 쓰거나, 스프링이 제공하는 StopWatch 코드를 집어넣고 빼긴 뭐 합니다. 그런식으로 테스트 해보고 싶은 메소드가 여러 개일 때도 귀찮겠죠?

2. 트랜잭션 처리

트랜잭션 처리는 거의 필수라는 생각이 듭니다. 저야.. 여태까지 스프링의 도움으로 아무런 어려움없이 간단하게 트랜잭션 기능을 사용하고 있지만, 이걸 스프링 없이 사용하려고 해보니 코딩 하기가 싫어졌습니다. 보기 싫은 try-catch 코드는 계속 늘어나고, 핵심 로직은 정글 속에 숨어버리니 말이죠.

3. 예외 변환

스프링에는 DataAccessException이라는 매우 잘 정의되어 있는 예외 계층 구조가 있습니다. 예전 하이버네이트 예외들은 몇 개 없었고 그나마도 Uncatched Exception이 아니였습니다. 이렇게 구조가 별로 안 좋은 예외들이 발생했을 때, 그걸 잡아서 잘 정의되어 있는 예외 계층 구조로 변환해서 다시 던지는 애스팩트는 제 3의 프레임워크를 사용할 때, 본인의 프레임워크나 애플리케이션에서 별도의 예외 계층 구조로 변환하고 싶을 때 유용합니다.

4. 아키텍처 검증

이것에 관련된 내용과 애스팩트는 어젯 밤에 공개했습니다. 유용하겠죠?

5. 기타

- 하이버네이트와 JDBC를 같이 사용할 때, DB 동기화 문제 해결.
- 멀티쓰레드 Safety 관려하여 롹을 가지고 수행해야 하는 메소드들에 일괄적으로 메소드 수행 전에 롹을 가지게 하고, 메소드 실행 후에롹을 반환하는 애스팩트
- 데드롹 등으로 인해, PessimisticLockingFailureException 이런 예외를 만났을 떄 재시도를 하는 애스팩트.
- 로깅, 인증, 권환, ...

찾아보니, 유용한 것들이 많이 있었습니다. 물론 이밖에도 상당히 여러 경우에 AOP를 활용할 수 있을 겁니다. 단지, 익숙하지 않다보니.. 잘 안 쓰게 되는데, 이번 주 주말 KSUG 세미나 마지막 발표를 통해서 어느 정도 AOP와 가까워지는 시간이 되길 바랍니다. 이번 세미나에서 위에 나열 한 것 중에 절반 정도를 살펴보겠습니다.
top