'AOP'에 해당되는 글 1건

  1. 2009.12.13 AOP : Aspect Oriented Programming

Aspect Oriented Programming

AOP는 프로그램 구조에 대한 다른 방식의 생각을 제공함으로써 OOP를 보완한다.

-       AOP는 문제를 바라보는 관점을 기준으로 프로그래밍하는 기법을 말한다.

-       문제를 해결하기 위한 핵심 관심 사항[1]과 전체에 적용되는 공통관심 사항[2]을 기준으로 프로그래밍함으로써 공통모듈을 여러 코드에 쉽게 적용할 수 있도록 도와준다.

-       AOP에서 중요한 개념은 「횡단 관점의 분리(Separation of Cross- Cutting Concern)」이다.

-       OOP를 더욱 OOP답게 만들어 준다.

 

OOP

OOP에서는 황단관점 분리를 위해 공통기능들을 하나의 클래스라는 단위로 모으고 그것들을 모듈로부터 분리함으로써 재사용성과 보수성을 높인다

각 모듈로부터 공통기능으로 분리하는 것으로 성공했지만 그 기능을 사용하기 위해 공통 기능을 호출하는 코드까지는 각 모듈로부터 분리할 수 없다. 그렇기 때문에 분리한 공통 기능을 이용하기 위한 코드가 각 모듈에 횡단으로 산재하게 된다.

 

AOP

AOP에서는 핵심 로직을 구현한 코드에서 공통 기능을 직접적으로 호출하지 않는다.

AOP에서는 분리한 공통 기능의 호출까지도 관점으로 다룬다. 그리고 이러한 각 모듈로 산재한 관점을 횡단 관점이라 부르고 있다.

AOP에서는 이러한 횡단 관점까지 분리함으로써 각 모듈로부터 관점에 관한 코드를 완전히 제거하는 것을 목표로 한다.

AOP에서는 핵심 로직을 구현한 코드를 컴파일 하거나, 컴파일된 클래스를 로딩하거나 또는 로딩한 클래스의 객체를 생성할때 핵심 로직 구현 코드 안에 공통기능이 삽입된다.

-       Advice - Joinpoint에 삽입되어져 동작할 수 있는 코드.

-       Joinpoint - 「클래스의 인스턴스 생성 시점」, 「메소드 호출 시점」및 「예외 발생 시점」과 같이 애플리케이션을 실행할 때 특정 작업이 시작되는 시점으로 Advice를 적용 가능한 지점.

-       Pointcut - 여러 개의 Joinpoint를 하나로 결합한(묶은).

-       Advisor - Advice Pointcut를 하나로 묶어 취급한 것.

-       Weaving - Advice를 핵심 로직 코드에 삽입하는 것.

-       Target - 핵심 로직을 구현하는 클래스.

-       Aspect - 여러 객체에 공통으로 적용되는 공통 관점 사항.

 

스프링 API를 이용한 AOP

스프링에서 AOP를 구현하는 과정은 다음과 같다.

1.     Advice 클래스를 작성한다.

2.     설정 파일에 Pointcut을 설정한다.

3.     설정 파일에 Advice Pointcut을 묶어 놓는 Advisor를 설정한다.

4.     설정 파일에 ProxyFactoryBean 클래스를 이용하여 대상 객체에 Advisor를 적용한다.

5.     getBean( ) 메소드로 빈 객체(프록시 객체)를 가져와 사용한다.

 

 

Advice 작성

스프링 AOP는 메소드 호출 관련 Advice만 제공하며 이들 Advice는 인터페이스형태로 제공된다.

인터페이스

설명

MethodBeforeAdvice

대상 객체의 메소드를 실행하기 전에 공통기능을 실행할때 사용되는 Advice

AfterReturningAdvice

대상 객체의 메소드 실행 이후에 공통기능을 실행할때 사용되는 Advice.

ThrowsAdvice

대상 객체의 메소드가 실행하는 도중 예외가 발생할 경우 공통기능을 실행할 때 사용되는 Advice.

MethodInterceptor

위 세가지를 하나로 묶은 Advice로 메소드 실행 전, , 예외 발생시 공통 기능을 실행할 수 있다.

 

 

MethodInterceptorm로 구현하는 방법

 

PerformanceCheckAdvice.java

public class PerformanceCheckAdvice implements MethodInterceptor {

 

        public Object invoke(MethodInvocation invocation) throws Throwable {

              

               String methodName = invocation.getMethod().getName();

               long start = System.nanoTime();

               System.out.println("[Log]Method Before --> " + methodName + "time check start");

               Object o = null;

               try {

                       //대상 객체의 메소드를 실행하기 전에 사용되는 코드

                       o = invocation.proceed();

                       //대상 객체의 메소드 실행 이후에 사용되는 코드

               } catch (Exception e) {

                       e.printStackTrace();

                       System.out.println("[Log]Method Error --> " + methodName );

               }

               long end =  System.nanoTime();

               System.out.println("[Log]Method After --> " + methodName + "processing time is "+(end-start)+"ns");         

              

               return o;

        }

 

}

 

GreetingServiceImpl.java

public class GreetingServiceImpl implements GreetingService {

 

        private String greeting;

       

        public GreetingServiceImpl(String greeting) {

               this.greeting = greeting;

        }

        public void sayHello(String name) {

               System.out.println(greeting + "\t" + name);

        }

}

 

applicationContext.xml

<bean id="greetingTarget" class="myspring.aop.GreetingServiceImpl">

        <constructor-arg>

               <value>Hello</value>

        </constructor-arg>

</bean>

 

<!-- 1. Advice 빈으로 등록 -->

<bean id="performanceAdvice" class="myspring.aop.PerformanceCheckAdvice" />

 

<!-- 2. pointcut 빈으로 등록 -->

<bean id="helloPointCut"

        class="org.springframework.aop.aspectj.AspectJExpressionPointcut">

        <property name="expression">

               <value>execution(public void say*(..))</value>

        </property>

</bean>

 

<!-- 3. Advisor 설정 -->

<bean id="helloAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">

        <property name="advice">

               <ref bean="performanceAdvice" />

        </property>

        <property name="pointcut">

               <ref bean="helloPointCut" />

        </property>

</bean>

 

<!-- 4. target객체에 위빙 -->

<bean id="greeting" class="org.springframework.aop.framework.ProxyFactoryBean">

        <property name="target">

               <ref bean="greetingTarget" />

        </property>

        <property name="interceptorNames">

               <list>

                       <value>helloAdvisor</value>

               </list>

        </property>

</bean>

 

 

참고자료

-       객체지향을 넘어 관점지향으로 AOP - ZDNET

 



[1] 핵심관심사항(core concern)

-       핵심로직, 핵심 비즈니스 로직(계좌이체, 이자계산, 대출처리 등)

[2] 공통관심사항(cress-cutting concern)

-       공통기능으로 어플리케이션 전반에 걸쳐 필요한 기능(로깅, 트랜잭션, 보안 등)

Posted by 피곤키오
,