공부/Spring

[Spring] CHAPTER 03 스프링의 AOP

JangGiraffe 2016. 2. 23. 19:58


DIxAOP 컨테이너의 AOP (Aspect oriented programming .. 관점지향 프로그래밍)

DI 컨테이너를 이용하는 것 만으로는 컴포넌트 내부의 오브젝트에 손을 쓸 수 없다. Aop를 이용하면 로그처리, 예외처리, 트랜잭션 처리 등 오브젝트 안에 있는 공통된 처리를 제거 할 수 있다. 이로인해 소스의 가독성이 올라가고 테스트하기 용이해진다.

AOP는 공통화해서 라이브러리화 할 수 있는 처리를 그 오브젝트에서 분리해서 별도의 오브젝트로 구현하는 기술이다!

 

 

 AOP의 용어  (한번 보고 이해가 완벽히 되지 않았지만 아래 내용들을 보고나서 한번 더 보니 조금은 이해가 갔다!)

횡단관심사 

본질적은 처리 이외의 처리(로그,예외 등)를 말하는듯함.. 

애스팩트 

횡단관심사의 동작과 그 횡단관심사를 적용하는 소스코드상의 포인트를 모은 것이다. 

조인포인트 

어드바이스가 실행하는 동작을 끼워 넣을 수 있는 때를 말한다. 

어드바이스 

조인트포인트에서 실행되는 코드다. 로그 출력이나 트랜잭션관리 등의 코드가 기술된다. 

포인트컷 

조인트포인트와 어드바이스 중간에서 처리가 조인트 포인트에 이르렀을 때 어드바이스를 호출할 지 선별한다 (필터역할)

ex)  메소드명에 Service라는 문자열이 있으면 호출한다 등의 필터역할을 함. 

 

 

 

스프링에서 제공하는 어드바이스

Before, After, AfterReturning, Around, AfterThrowing이 있다. 예를들어 메소드 시작과 종료 로그를 출력하고 싶다면 Before, After(또는 AfterReturning) 어드바이스에 로그처리를 기술하거나 Around에 하면 됨.

 

 어드바이스의 형태

설명 

Before 

조인포인트 앞에서 실행할 어드바이스 

After

조인포인트 뒤에서 실행할 어드바이스   (정상 종료시 삽입)

AfterReturning 

조인포인트가 완전히 정상 종료한 다음에 실행되는 어드바이스 (정상 종료시 삽입) 

Around 

조인포인트가 앞뒤에서 실행되는 어드바이스 (예외 발생시에도 삽입) 

AfterThorwing 

조인포인트에서 예외가 발생했을 때 실행되는 어드바이스. 

트랜잭션 처리는 AOP 제품에서 이미 제공해줌.(5장 참고)

어드바이스와 자바클래스가 다른점은 ? ->이따가 말해줌

 

3.4 프록시를 이용한 AOP(생략)

AOP

->우선 하면 안되는 것 : AOP를 이용해 업무처리를 분리하는 것 (왜냐하면 소스코드의 가독성이 현저하게 떨어지기 때문이다)

 

예시를 들어 이해를 돕겠음.

public class Product{

    int price;

    public int getPrice(){

      return price;

    }

 위의 코드에서 price가 100인데 getPrice메소드를 호출했을 때 105가 나온다면? 황당하겠지. AOP를 이용해 업무처리해야할 것을 분리해서 코드에 가독성에 혼란을 줬기 때문이야. 안에서 +5가되는 코드가 돌아간다는거지..

그래서 공통화 할 수 있는 처리만 AOP로 분리해야한다라는것..

 

스프링의 AOP

스프링의 매력은 DI와 AOP를 조합했을 때 발휘된다 해도 과언이 아니라고 한다. AOP역시 애노테이션과 Bean정의파일 설정 2가지 방법으로 이용 할 수 있다.

 

애노테이션으로 이용하는 방법.

그 클래스가 Aspect임을 나타내는 @Aspect를 클래스 앞에 써준다. 그리고 메소드 선언 앞에 @Before등등의 어드바이스 형태를 잡아주면 된다. 포인트컷의 필터링 조건을 넣고 싶으면 @Before("execution(메서드명)")등으로 이용 (밑에서 더 자세히 언급하겠습니다.)

Bean정의파일에서는 aop스키마와 AOP를 애노테이션으로 적용한다는 것을 선언하는

<aop:aspectj-autoprox />

태그를 추가하면 된다.

 

포인트컷 기술 방법

애노테이션 괄호 안에 "execution(*findProduct(String))"과 같은 형식으로 기술. or,and, not , ||,&&,!를 사용 할 수 있다.

ex) execution(**..AopExBean.exMethod()) or execution(**..AopExBeanParent.exMethod())

 

애노테이션으로 어드바이스 만들기

Before,After 어드바이스 작성법은 간단하다. 메소드명은 임의, 메소드의 인수는 없는게 기본, 메소드의 반환값은 void가 기본.

메소드 인수에 JointPoint를 설정하면 메소드 이름과 인수값을 알 수 있다.

ex)

@Before("execution(* findProduct(String))")

public void foo(JointPoint jp){

  Signature sig = jp.getSignature();  // 메소드 이름.

  Object[] objs = jp.getArgs(); //인수값

}

AfterReturning 어드바이스역시 간단함. 메소드명 임의, 인수는 AOP적용 대상이 된 메소드의 반환형. 메소드의 반환값은 void가 기본.

 

Around어드바이스는 다른 어드바이스와 달리 AOP의 대상이 되는 메소드의 호출을 어드바이스 안에서 직접 해야만 한다.  AOP의 대상이 되는 메소드의 호출은 proceed 메소드를 이용해 이뤄짐. 또한 이것은 반환값이므로 확실히 리턴하도록 하자.반환하지 않아도 컴파일오류가 나지 않기 때문에 주의하자. proceed메소드를 빼먹는다면 애스펙트 대상이 된 메소드가 호출되지 않으므로 더 주의하자. 

ProceedingJoinPoint 클래스는 앞서 등장한 조인포인트를 상속받으므로 AOP의 대상이 된 메소드의 이름 등도 가져올 수 있다.

예제를 통해 이해를 돕자! 

 ex)

@Around("execution(* getMessage())")
public String fuga(ProceedingJoinPoint pjp) throws Throwable{
   String message = (String)pjp.proceed();
   return message;
}

AfterThrowing 어드바이스는 다른 어드바이스와 달리 AOP의 대상이 되는 메소드에서 예외가 발생했을 때만 동작하는 어드바이스다.

ex) @AfterThorwing(value = "PrimitivePointcut",throwing="예외의 변수명")

    public void methodName(Exception 예외의변수명)

.....

 

Bean정의파일을 이용한 AOP 

ex)

<aop:config>

  <aop:aspect id = "이름아무거나" ref = "클래스 이름 첫글자를 소문자로(@Component사용시에 한함)">

      <aop:pointcut id = "pc" expression -"execution(*findProduct(string))"/>

     <aop:before pointcut-ref="pc" method="before"/>

   </aop:aspect>

</aop:config> 

 

@Component를 이용하지 않을 땐

<bean id ="myFirstAspect" class="sample.aop.MyFirstAspect"/>를 추가.

aop:config : AOP의 정의를 하는 최상위 엘리먼트. 하나의 Bean 정의 파일에 여러 개를 기술 할 수 있다.

aop:aspect : Aspect의 정의를 한다. aop:config의 시작과 종료 사이에 여러개의 Aspect를 정의할 수 있다.

aop:pointcut 포인트컷을 정의한다. aop:aspect의 시작과 종료 사이에 여러개의 포인트컷을 정의할 수 있다.

 

반응형