본문 바로가기

스프링 프레임워크

뉴렉처[스프링 프레임워크_AOP] 1강 ~8강

1강 - AOP(Aspect Oriented Programming) 이란?

Aspect 의 의미 : "관점" 이라는 뜻.

개발을 하다보니 사용자의 관점만이 아닌 개발자의 관점, 운영자(관리자)의 관점도 존재한다.

 

AOP란,

사용자의 관점에서 주 업무 로직과 개발자의 관점 또는 운영자의 관점의 보조 업무 로직을 

어떻게 분리하고 결합하여 프로그램을 만들 것인가? 에 대한 방법론.

 

*용어: Primary(Core) ConcernCross-cutting Concern

                (주 업무)                        (보조 업무)

 

(보조업무는 탈 부착이 가능하다.)

과거에는 Cross-cutting 하는 것이 쉽지 않았다.

주 업무 소스코드에 직접 보조 업무 소스코드가 박혀 있기때문에 소스코드를 직접 손댔어야 했기때문이다.

=> 위와 같은 이유로 수정 후 배포 작업이 매번 번거로웠다.

과거의 구조

이러한 단점을 극복하고자 AOP 방법론이 등장하였다.

 

보조 업무의 Aspect(관점) 코드를 직접 주 업무 소스코드에 꽂아 넣지 않고, 마치 꽂아 넣은 것 처럼 실행 될 수 있도록

하는 방법론이다.

(물리적으로는 따로 분리되어있지만, 논리적으로는 하나로 이루어져있는 것처럼 실행된다.)

AOP의 구조

2강 - AOP 자바 코드 이해하기

 

과거 : 주 업무 로직과 보조 업무 로직이 함께 존재

 

현재 : 주 업무 로직과 보조 업무 로직을 분리해서 처리

 

[구현 틀]

[구현 예]

 

위에서 순수 자바로 만든 examProxy(주 업무 + 보조 업무)의 대한 소스 코드를 수정할때 일반적으로 수정이 불편하다.

스프링에서 Proxy의 결합&분리를 Spring DI로 편리하게 해결 가능하다.

 

3강 - 순수 자바로 AOP 구현해보기

 

Proxy 는 "가짜" 라는 뜻을 가지고 있다.

 

Exam의 Proxy를 만들어주는 것이다. 

사용자 입장에서는 Exam과 Proxy가 똑같아 보이기 때문에 Exam을 쓰는 것 처럼 느낄 수 있다.

Exam 은 주 업무만 가지고 있고, Proxy 는 주 업무 + 보조 업무 를 둘 다 가지고 있다.

==> Exam(주 업무의 기능만) <=> Proxy(주 업무 + 보조 업무 기능)

 

따라서 개발자와 운영자는 Proxy를 사용하여 주 업무 기능과 보조 업무 기능을 동시에 사용하고,

사용자에게는 주 업무만 사용하게 Exam을 붙여주면 된다.

 

프록시 생성하는 기본 틀

Exam proxy = Proxy.newProxyInstance(loader, interfaces, h); 

 

* [매개변수 분석]

loader : 실제 업무 할 수 있게끔 실제의 정보를 갖고 있는 클래스

interfaces : loader(주 업무)의 인터페이스들의 정보를 전달(복수 임으로 배열로 전달)

h : 곁다리 업무를 꽂을 수 있는 부분

위와 같이 Proxy를 만들어 곁다리 업무를 껴 넣으면

System.out.printf("total is %d \n", proxy.total());

System.out.printf("avg is %f \n", proxy.avg());

 

각각 다른 total() 메서드와 avg() 메서드를 사용할때 Proxy를 활용할 수 있다.

Proxy 실행 결과

주 업무만 사용하려면 exam 객체를 사용하고,

보조 업무도 같이 사용하고 싶다면 proxy 객체를 사용하면 된다.

 

4강 - 스프링 AOP로 AroundAdvice 구현하기

스프링이 제공하고 있는 Proxy 클래스를 사용해보자.

=> 1. 주 업무 2. 보조 업무 만든 후 IoC 컨테이너에 담아 두기!!!

 

*[보조 업무의 유형]

 

스프링으로 AOP를 구현해 보자!

 

1. 주 업무를 갖고 있는 NewlecExam 클래스를 bean 등록해준다.

2. 보조 업무의 로직이 정의되어있는 LogAroundAdvice 클래스를 bean 등록해준다.

3. 스프링에서 지원하는 Proxy 생성 클래스를 이용하여 주 업무와 보조 업무를 등록해준다.

 

 

보조 업무의 로직이 정의되어있는 LogAroundAdvice 클래스

 

5강 - BeforeAdvice 구현하기

 

6강 - After Returning / Throwing Advice 구현하기

Before Advice 와 After Advice 의 매개변수가 조금 차이가 있다.

 

매개변수에 주 업무가 끝나고 반환된 값이 들어있다.

=> After Advice는 주 업무가 끝나고 처리되는 보조 업무이기 때문에 주 업무가 실행되고 반환되는 값을

사용할 일이 생기면 사용하라고 매개변수로 같이 넘어온다.

 

Throwing Advice 는 ThrowsAdvice를 해도 밑줄이 안뜬다.

Why?

==> 어떤 예외처리에 관해서 보조 업무 처리를 해야하는지 모르기 때문이다.

 

따라서 우리가 예외처리를 하고 싶은 것의 보조 업무 함수를 만들어야한다.

[틀 Ex]

public void afterThrowing(예외종류 e) throws Throwable{

 

}

[실제 Ex] ArrayIndexOutOfBoundsException 예외처리에 대한 보조 업무 로직을 구현하기.

public void afterThrowing(ArrayIndexOutOfBoundsException e) throws Throwable{

 

}

 

3가지 종류를 한번에 종류

==> 다음 시간에는 total() 메서드, avg() 메서드를 모두 실행할때 로그(보조 업무)가 발생하는 것이 아닌

특정 메소드(특정 업무)를 실행할때만 로그(보조 업무)가 실행될 수 있도록 하게 만들어보자!

 

7강 - Point Cut(Weaving, Join Point)

 

Proxy를 이용해서 곁다리 업무와 주 업무(target)를 연결하는 것(하얀색 실선)을 위빙(Weaving)이라고 한다.

곁다리 업무가 연결 대상으로 삼고 있는 주 업무(target)를 조인 포인트(Join Point)라고 한다.

 

이전에는 total() 메서드[join point]와 avg() 메서드[join point]에(모든 주 업무) 위빙(Weaving)이 되어 있었다.

==> 이번 시간에는 total() 메서드에만 위빙을 하는 것Pointcuts 이라고 한다.

 

setting.xml 파일에서

 

1. 특정 주 업무만 실행할 수 있게 Pointcut을 설정하는 Pointcut bean 등록하기

<bean id="classicPointCut" class="org.springframework.aop.support.NameMatchMethodPointcut">

     <property name="mappedName" value="total" />

</bean>

 

2. 위에 설정한 Pointcut과 Advice를 연결해주는 설정소스

classicBeforeAdvisor 이라는 bean에서 보조업무 등록하는 setAdvice포인트 컷을 등록하는 setPointcut을 해준다.

==> 따라서 classicBeforeAdvisor은 주 업무 전에 보조 업무가 실행되고, 주 업무는 total()

 

ex. BeforeAdvice 를 할때 보조업무를 total()만 실행하게 하고 싶다.

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

     <!-- setAdvice()를 말하는 것 -->

     <property name="advice" ref="logBeforeAdvice"></property>

     <!-- setPointcut()을 말하는 것 -->

     <property name="pointcut" ref="classicPointCut"></property>

</bean>

 

3. 프록시에 위에서 만든 조인 포인트(classicBeforeAdvisor)를 등록해준다.

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

           <property name="target" ref="target" />

           <property name="interceptorNames">

                     <list>                                  

                                <value>logAroundAdvice</value>

                                <value>classicBeforeAdvisor</value>

                                <!-- <value>logBeforeAdvice</value> -->

                                <value>logAfterReturningAdvice</value>

                                <value>logAfterThrowingAdvice</value>

                     </list>            

           </property>

</bean>

 

전체 소스

8강 - 간소화된 Advisor

Pointcut을 구현하는데 있어 이전 시간에 너무 복잡하게 만들었다.

 

 

Pointcut 기능을 내재하고 있는 Advisor이 있다. [Advice + Pointcut]

ex. total() 메서드만 실행하게 할때

<bean id="classicBeforeAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">

     <!-- setAdvice()를 말하는것 -->

     <property name="advice" ref="logBeforeAdvice" />

     <property name="mappedName" value="total" />

</bean>

 

ex. total() 메서드와 더불어 복수의 메서드만 실행하게 할때 list로 등록

<bean id="classicBeforeAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">

           <!-- setAdvide()를 말하는것 -->

           <property name="advice" ref="logBeforeAdvice" />

           <property name="mappedNames" >

                     <list>

                                <value>total</value>

                                <value>avg</value>

                     </list>

           </property>

</bean>

 

* 이름이 비슷한 패턴의 메소드명을 갖고 있는 메소드를 Pointcut 지정하려면 어떻게 해야할까?

 

 

 

 

 

 

 

 

출처: 뉴렉쳐 (https://youtu.be/y2JkXjOocZ4)