Step by Step

Spring 공부 2021-03-17

unboxing 2021. 3. 17. 00:14

뉴렉처 Spring 18강

 

AOP란? (Aspect Oriented Programming)

AOP는 스프링과 상관없는 방법론

 

사용자 관점이아닌 개발자나 운영자가 필요에따라서 추가하는 부가적인 코드 (주업무가 아닌업무)

 

로그처리 , 보안처리 , 트랜잭션처리 등등 (사용자 요구내용을 수반하기위한 보조업무)

보조업무 (관점이 다른업무)
주업무
보조업무 (관점이 다른업무)

 

AOP : 관점에 해당하는 코드를 직접꽂아놓지않고 꽂아놓은것처럼 실행되게 하는 방법

뉴렉처 Spring 18강 캡처

Spring을 사용하게되면 뺏다가 꽂았다 하는것이 쉽게 구현이 된다.


 

AOP 구현방식 이해하기

 

사용자가 프락시 클래스를 호출 -> 프락시 클래스에 구현되는 Cross-cutting Concern 와 사용자가 원하는 함수 실행

뉴렉처 Spring 19강 캡처

 

Spring을 사용하게되면 프락시를 결합했다가 분리하는것을 Spring DI로 쉽게 해결 할수있다.


AOP 코드 구현하기

 

AOP코드를 구현해보기 위해서 spring.aop 패키지에 Program 이름의 파일을 추가한다.

 

테스트를 위해서 기존에 있던 Exam 클래스를 사용하기위해 Exam클래스가있던 spring.di.entity 를 

spring.aop.entity 패키지에 카피해서 가져온다.

테스트를 위해 aop.entity안에 있는 NewlecExam의 total() 메소드와 avg() 메소드를 사용할것이다.

 

 

사용자가 요구하는 기능의 수준에서의 total() 메소드 출력 (aop의 Exam,NewlecExam)

 

개발자(관리자) 관점에서의 새로운 코드추가 ( 보조업무 ) 

Thread.sleep(200) 은 테스트를 위해 임시로 시간을 주기위함

 

AOP는 이렇게 직접 코드에 추가하지않고 보조업무를 따로만들어서 연결하는것 

보조업무를 주석처리 한다.  (Spring을 사용하지않고 AOP 구현)

연결 해줄수있는 프락시(Proxy) 객체 생성

Proxy.newProxyInstance( 실질적인 객체 , 구현받은 인터페이스들 (배열) , 보조업무핸들러 ) 

보조업무를 사용하기위한 핸들러인 InvocationHandler() 를 익명클래스로 작성

invoke메소드의 method를 사용해 실제업무를 가져온다. method.invoke(실제업무,호출한메소드의 인자값 args)

필요에 따라 proxy를 이용해 사용 할수있다. 


스프링 AOP로 AroundAdvice 구현하기

 

Advice 종류

Before : 앞에만 필요한 보조업무 (MethodBeforeAdvice)

After returnnig : 뒤에만 필요한 보조업무 (AfterReturningAdvice)

After throwing : 예외를 처리하는 보조업무 (ThrowsAdvice)

Around : 앞뒤로 전부 필요한 보조업무 (Methodinterceptor)

 

스프링을 활용해 AOP를 구현하기위해서 

 

spring.aop패키지에 xml파일을 추가한다.

 

Setting.xml

target이라는 이름의 aop패키지 안에있는 NewlecExam 객체를 생성해주고

앞뒤 보조업무내용을 가지고있는 logAroundAdvice 객체를 생성 (advice중에 Around 구현)

 

proxy객체를 생성한다 class는 org.springframework.aop.framework.ProxyFactoryBean 

(proxy 의 class에 들어갈 패키지명을 다 기억하기 쉽지않으니

  xml이 아닌 java프로젝으로 가서 순서대로 입력후 복사붙여넣기로 가져오면 오타걱정이 없다)

 

proxy를 열어서 실제 NewlecExam의 객체를 넣어준다.

<property name="target" ref="target"/>    (여기서의 name에 들어있는 target은 setTarget이다)

 

그리고 보조업무를 넣어주기위한 핸들러 <property name="interceptorNames"> 를 사용한다.

복수형이기때문에 <list>안(참조목록 안) 에 <value>값으로 보조업무내용을 가지고있는 bean id  값을 넣어준다.

 


 

LogAroundAdvice 클래스

보조업무를 담은 클래스를 생성하기위해 spring.aop.divce안의 LogAroundAdvice 클래스를 생성해준다.

AroundAdivce를 담기위한 클래스는 구현해야할 인터페이스가 있다. ( Methodinterceptor )

구현할 목록을 추가한다 ( 스프링을 사용하지않고 AOP를 구현했을 때 생성했던 익명클래스의 메소드와 비슷한 구조 )

invocation.proceed() 로 주업무를 호출한다. ( invoke대신 사용, 스프링이 처리해준다 )


메인 으로 돌아와서 proxy의 이름을 가진 Bean으로 Exam객체를 가져온뒤 실행해보면 잘 나오는것을 볼수있다.

 


필요에 따라 사용/비사용 하는것을 설정에서 수정하는것만으로도 해결할수있다.

코드는 같지만 설정을 바꾸어 로직이 있고 없고를 확인 할수있다.


 

BeforeAdvice 구현하기

 

setting.xml

BeforeAdvice를 구현하기위해 xml에서 BeforeAdvice를 구현한 클래스의 빈을 생성해준다.

property 의 list안에 value를 지우고 하나로 해도되겠지만 AroundAdvice를 지우지않고 그냥

logBeforeAdvice를 추가하도록한다.

 

 

LogBeforeAdvice 클래스

aop.advice 패키지안에 LogBeforeAdvice 클래스를 하나추가한다.

BeforAdivce를 담기위한 클래스는 구현해야할 인터페이스가 MethodBeforeAdvice 다. 

앞에서 실행할 로직을 구현한 메소드 안에 작성해주면된다.

현재호출되고 있는 함수에 대한이름이나 파라미터값을 얻고싶다면 method 를 사용하면되고 

타겟에대한 객체를 이용하고싶다면 target을 이용하면된다.

 

실행될때마다 앞부분에 로직이 출력되는것을 볼수있다.


After Returning Advice 구현하기

 

setting.xml

AfterReturningAdvice 를 구현하기위해 xml에서 AfterReturningAdvice를 구현한 클래스의 빈을 생성해준다.

BeforeAdvice와 같이 property 의 list안에 value값으로 구현클래스의 아이디값을 추가해준다

 

LogAfterReturningAdvice 클래스

aop.advice 패키지안에 LogAfterReturningAdvice 클래스를 하나추가한다.

AfterReturningAdvice를 담기위한 클래스는 구현해야할 인터페이스가 AfterReturningAdvice 다. 

After는 함수가 호출되고나서 반환값을 가지고 처리할 내용있으면 사용할수있게 매개변수로

리턴값,메소드,아규먼트,타겟 등을  넘겨받는다 (필요시 사용가능)

구현한 메소드안에 어떤값을 사용할수있는지 테스트해보기위해서 매개변수 두가지만 사용해본다

(returnValue와 method)

 

뒤쪽에 로직이 실행되는것을 볼수있다.

After Throwing Advice 구현하기

예외가 발생했을때 실행이된다.

setting.xml

AfterThrowingAdvice 를 구현하기위해 xml에서 AfterThrowingAdvice를 구현한 클래스의 빈을 생성해준다.

property 의 list안에 value값으로 구현클래스의 아이디값을 추가해준다

 

LogAfterThrowingAdvice 클래스

aop.advice 패키지안에 LogAfterThrowingAdvice 클래스를 하나추가한다.

AfterThrowingAdvice를 담기위한 클래스는 구현해야할 인터페이스가 ThrowingAdvice 

 

어떠한 예외가 발생하냐에따라서 함수의 인자가 달라지기 때문에 어떤 예외가 처리될것인지 모르기때문에

클릭으로 메소드를 구현할수가 없다.

 

기본적인 형태

어떤 예외인지 모른다.

테스트하기위해 IllegalArgumentException예외가 나올시 예외메세지를 출력하도록한다.

 

예외없이 정상적으로 작동이 될때는 실행되지않지만 예외가 나타났을때는 실행이되는 로직이다.

테스트해보기위해 임의로 IllegalArgumentException 을 발생 시키도록한다.

NewlecExam 클래스의 total() 메소드에 국어점수가 100점이상이면 IllegalArgumentException 를 발생시킨다.

Setting.xml에서 국어점수를 101점으로 수정한다.

 

그 후에 실행하면 IllegalArgumentException가 발생하면서 콘솔창에는 AfterThrowingAdvice 가 실행되는것을 볼수있다.


 

 


Point Cut (Weaving , JoinPoint)

 

Pointcuts : 원하는 메소드만 weaving할수있게 해주는것

JoinPoint : 보조업무가 대상으로 삼고있는 주 업무

weaving : 프록시가 주업무와 보조업무를 조립(뜨개질) 연결해주는 과정

 

PointCut 사용하기

 

(1) 기존의 방법

프록시 위쪽에 Pointcut을 사용하기 위한 Bean작성 해준다. (total만 사용하기위한 PointCut)

property의 name은  "mappedName"

 

Pointcut과 Advisor를 연결할수있는 도구 설정 (현재 BeforeAdvisor를 PointCut과 연결할것)

property 설정은 name = advice 는 연결할 advice의 bean id를 사용

name = pointcut 에는 연결할 pointcut의 bean id를 사용해서 연결해준다.

 

프록시 설정에서는 

기존에있던 logBeforeAdvice 대신 연결시킨 classicBeforeAdvisor를 사용한다.

 

Pointcut을 설정하면 total() 메소드를 실행할때에만 beforeAdvisor가 나오는것을 확인할수있다.

 

(2) 간소화된 방법

결합된 형태의 Advisor를 사용해서 코드를 줄일수있다. (PointCut을 품은 Advisor)

NameMatchMethodPointcutAdvisor 를 사용하여 Pointcut까지 함께 적용해 코드를 줄일수있다.

 

mappedName에 s 를 더 추가로 붙여서 property를 열고 <list>태그와 <value>태그를 사용하여

여러개의 함수를 추가할수있다.

 

 

(3) 정규식 사용  RegexpMethodPointcutAdvisor

Reqular Expression (정규식패턴 사용)

property name을 patterns 로 바꿔준뒤 value값을 .*to.* 입력(메소드 이름중에서 to가들어간걸 찾는다)

 .*  : 어떠한 문자도 올수있다

정규식 패턴을 이용해 to가 들어간 total() 메소드에서 사용된다.

패턴을 가지고있는 Advisor가 정상적으로 실행

 

 

 

 

 

 

뉴렉처 Spring 25강 완