Toby’s 스프링 AOP 마무리

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

 AOP 챕터가 다소 크다는 느낌을 받았다. 스프링 AOP 기능 뿐 아니라 트랜잭션에 관한 설명도 상당 부분이 나온다. 하지만 스프링 트랜잭션을 이해하려면 스프링 AOP에 대한 이해가 필수적이고 스프링 AOP를 이해하기 위한 좋은 예로 스프링 트랜잭션 만큰 좋은 것도 없다고 생각이 든다. 따라서 스프링 AOP를 설명한 굉장한 분량만큼이나 그 노고를 느낄 수 있었다. 특히 중간 중간 텍스트로 인해 지칠 수 있는 독자들을 위한 그림들은 상당히 단순 명료하면서도 배려적이다.
그 중에서 가장 눈길을 끈 곳은 포인트컷 테스트였다. 정말 대박이었다. 예전에 읽었을 때에도 감명을 받고 사실 그 내용을 바탕으로 포인트컷 표현식 테스트에 대한 블로깅까지 했던적이 있다. AOP를 사용할 때 항상 고민하던 부분이었다. 도대체 이 포인트컷이 어디에 적용이 되는건지 확실하게 알 수 없을까… 이클립스나 인텔리J 도움 없이 조인포인트를 확인할 수 있는 아주 간단한 방법이 있다는 것을 보고는 새삼 놀랐다. 내가 너무 모른다는 사실도 한몫했다.
또한 execution 포인트컷에서 사용하는 표현식을 분석한 표역시 대단하다는 생각밖에 들지 않는다. AOP 용어도 이해하고 대강의 사용법까지 익히더라도 항상 막막한 부분은 바로 표현식 작성이었다. 지금 읽은 부분에서는 아직 args나 this, type같은 건 등장하지 않았지만 아마 2부에서 더 자세하게 다룰 것 같다.
AOP 용어 정의를 거의 맨 뒤에서 설명하는 이럭 획기적인 방식으로도 AOP를 더 쉽고 알차게 학습 할 수 있다는 사실에 여러분도 놀랐것이다.  

Toby’s 스프링 AOP 등장 배경을 읽으며…

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

그 등장 배경을 이해하는 것은 결코 쉽지 않다. 그만큼 간단한 절차가 아니기 때문이다. 조금 길다 싶을 정도로 여러 단계의 정제 과정을 걸치게 된다. 그 과정 하나 하나에 문제, 해결책, 장점, 단점 또 그 단점을 극복하는 해결책 그 결과의 장점과 단점. 다시 또 그 단점을 극복하는 .. 이런식으로 꼬리에 꼬리를 물고 가다가 결국에 스프링 AOP의 핵심 요소들이 등장하게 된다. 
마침내 어드바이스, 포인트컷, 어드바이져, 포인트컷 표현식등 AOP 용어가 들려오더라도 전혀 당황스럽지 않다. 그 용어들의 느낌과 개념이 자연스럽게 이해된다. 어드바이스는 머다. 포인트컷은 머다. 라는 식으로 AOP 무식하게 학습했던 과거가 부끄럽게 느껴진다. 이런 학습방법으로 접근했다면 천천히 가는 것처럼 느껴졌겠지만 오히려 더 확실하게 개념을 익힐 수 있었을텐데 라는 생각이 많이 들었다.
이 부분에서 꼭 집중해서 살펴봐야 할 부분이 있다면 BeanPostProcessor가 언급된 부분이다. 그 부분을 자세히 읽으면 AOP 적용시 흔히 실수하는 상황을 잘 캐치할 수 있을 것이다. 보통 빈 설정을 잘못해서 AOP가 적용되지 않는 경우가 많은데 왜 그런지 그 이유와 원인을 이해할 수 있을 것이다.
이제 본격적으로 스프링 AOP에 대한 내용을 읽어야 하는데 시간이 늦어서 집에가서 봐야겠다..
그 작업을 target으로 집안청소 Advice와 퇴근 후 일정 Pointcut을 조합한 Advisor를 감지하여 프록시를 만들어 주는 DefaultAdvisorAutoProxyCreator를 설정해야겠다.

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

@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 하나로 모두 통합하는 것도 좋겠습니다.

ProxyFactoryBean을 이용한 초간단 AOP 구현

스프링 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님의 스프링 책을 참조하세요.

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

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

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

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

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

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

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

사용자 삽입 이미지
귿~ 잘 해결됐네요. 그렇게 하랍니다. 번역서에서는 좀 더 분명하게 적어드리겠습니다.