이전 섹션에서 적용했던 adviceadvised 객체(advice가 삽입된 객체)에 advised 메서드가 다소 난잡하게 적용되었습니다. ConsoleLoggingAroundAdvice는 간단하게 타겟객체(Target object)상의 모든 메서드(인터페이스가 구현된 부분)를 가로챌수 있습니다. 이러한 것은 간단한 예제와 같은 것들에서는 쉽게 적용이 가능하고 또한 적합하기도 합니다. 그러나 여러분이 어떤 객체의 어떤 메서드에 advice 코드를 삽입하기를 원할 때 이런 방법이 적합하지 않을수도 있다는 겁니다.


예를 들어서 여러분은 advice 코드에 삽입된 메서드로 실행을 시작하기를 원할수 있습니다. 또는 여러분이 advice코드에 삽입된 특정 런타임 값으로 호출되는 메서드로 프로그램의 실행을 원할수도 있으며 Lockable 어트리뷰트를 이용하는 메서드를 이용한 실행을 원할수도 있습니다.


Spring.NET AOP 매카니즘에서 우리가 수행하는 작업은 IPointcut 인터페이스에 의해 캡슐화 되고 advice가 잘 적용되는지 구별하기 위해 사용합니다. Spring.NET은 IPointcut 인터페이스의 많은 out-of-the-box 구현을 제공합니다. 만약에 코드에 아무것도 명시적 구현이되어 있지 않다면 구현은 표준적인 TruePointcut을 사용하게 됩니다. Pointcut이라는 이름에서 보듯 이것은 항상 매칭되는 모든 메서드를 찾아냅니다. 그러면 이것을 구현해보기 위해 이전에 작성된 advice의 구성을 문자 'Do'를 사용하는 메서드를 작성하여 변경해 보겠습니다.


먼저 우리는 ICommand 인터페이스를 변경할 것 입니다.


public interface ICommand

{

    void Execute();

    void DoExecute();

}

public class ServiceCommand : ICommand

{

    public void Execute()

    {

        Console.Out.WriteLine("Service implementation : Execute()...");

    }

    public void DoExecute()

    {

        Console.Out.WriteLine("Service implementation : DoExecute()...");

    }

}


코드에서 보시는 것 처럼 advice 자신이 변경될 필요가 없음을 주의깊게 봐야 합니다.

(advice 자신은 ConsoleLoggingAroundAdvice 클래스내에 캡슐화 되어 있습니다.)


아래의 코드를 보시면 문자 'Do'가 코드에 추가되어 있고 이러한 방식으로 프로그램의 구성을 수정합니다.

ProxyFactory factory = new ProxyFactory(new ServiceCommand());

factory.AddAdvisor(new DefaultPointcutAdvisor(

    new SdkRegularExpressionMethodPointcut("Do"),

    new ConsoleLoggingAroundAdvice()));

ICommand command = (ICommand) factory.GetProxy();

command.DoExecute();


이 코드가 실행되는 결과는 다음과 같습니다.

Intercepted call : about to invoke next item in chain...

Service implementation...

Intercepted call : returned


이런 결과가 나오는 것은 advice가 'Do' 문자를 포함하여 실행되는 메서드 때문입니다.


출력 결과를 비교해 보기 위해 이번에는 Execute() 메서드를 호출해 보는 것으로 코드를 변경해 보겠습니다.

ProxyFactory factory = new ProxyFactory(new ServiceCommand());

factory.AddAdvisor(new DefaultPointcutAdvisor(

    new SdkRegularExpressionMethodPointcut("Do"),

    new ConsoleLoggingAroundAdvice()));

ICommand command = (ICommand) factory.GetProxy();


//이 메서드 이름에는 'Do'가 없습니다.

command.Execute();


이것의 출력결과는 다음과 같습니다.

Service implementation...


이러한 결과가 나오게 되는 원인은 조금 있다가 설명하겠습니다.

앞에 작성한 프로그래밍 구성 예제와 비슷한 XML 구성은 아래와 같습니다.

<object id="consoleLoggingAroundAdvice"

           type="Spring.Aop.Support.RegularExpressionMethodPointcutAdvisor">

    <property name="pattern" value="Do"/>

    <property name="advice">

        <object type="Spring.Examples.AopQuickStart.ConsoleLoggingAroundAdvice"/>

    </property>

</object >

<object id="myServiceObject"

            type="Spring.Aop.Framework.ProxyFactoryObject">

    <property name="target">

        <object id="myServiceObjectTarget"

                    type="Spring.Examples.AopQuickStart.ServiceCommand"/>

    </property>

    <property name="interceptorNames">

        <list>

            <value>consoleLoggingAroundAdvice</value>

        </list>

    </property>

</object>


이 코드를 쭈욱 보시면서 아마도 눈치를 채셨을 겁니다. Pointcut의 취급이 advisor의 컨셉을 소개한 것이라는 것을 말입니다. 

Advisor는 pointcut의 합성과 advice 자신이 아닙니다. ConsoleLoggingAroundAdvice 객체는 'Do'패턴과 일치하는 advised 객체의 모든 메서드에 advice가 적용될 advisor를 정의합니다.

패턴의 일치는 RegularExpressionMethodPointcutAdvisor 클래스의 패턴 속성에 간단한 문자열 값을 제공함으로써 이뤄지게 됩니다.







profile

소프트웨어라는 도구를 천문분야에 접목하는 것에 대해 관심을 가지고 있는 1인 입니다.

 

 

한국천문연구원(KASI) 한국형 외계지적생명체 탐색 기술자문 (2010)

Microsoft Visual C# MVP(2009-2010)

세티의 Lonely Star 블로그 운영


facebook: http://www.facebook.com/setipark