개발/KH국비지원과정

[KH국비지원 웹개발자 과정] Day_66 키워드 스프링 AOP, 프록시

mabb 2022. 10. 8. 11:01
반응형

 

해당 포스팅은 강의 복기용으로 키워드를 기록하는 용도의 포스팅입니다.
--------------------------------------------------------------------------------------------------

스프링 AOP
Aspect Oriented Programming ,관점지향프로그래밍
: 일반적으로 사용하는 클래스(서비스, 다오 등)에서 중복되는 공통코드부분(트랜잭션, 로그)등을 별도의 영역으로 분리해 내고 코드가 실행되기 전이나 후의 시점에 해당 코드를 붙여넣음으로써 소스코드의 중복을 줄이고 필요할 때마다 가져다 쓸 수 있게 객체화하는 기술이다.


이는 프록시 (Proxy,대리인,대행자) 기능에 의해 이루어진다.
타겟 메소드(aop를 적용할 메소드)가 실행될 때 
AOP를 적용하지 않는다면 정상적인 프로그램흐름에서 실행이 되지만
AOP를 설정할 경우 프록시가 이 메소드의 실행을 낚아채서 대신 실행한다.(대리인)
이렇게 대신 실행하면서 그 메소드의 실행 전이나 후 또는 전후, 또는 예외발생 시 특정 코드(어드바이스, 공통(부가)기능을 정의한 코드) 를 끼워넣어 실행하는 것이다.

AOP 사용을 정리하자면
1. 프록시 (타겟으로 설정한 메소드를 대리 실행하면서 공통기능을 필요한 시점에 끼워 넣는 역할) 를 설정해야하고
2. 공통기능(부가기능, 로거, 트랜잭션 등) 을 만들어야 하고(어드바이스)
3. 이 공통기능을 적용할 메소드를 정해야하고 (포인트컷 표현식)
4. 어드바이스 실행 시점을 정해야 한다.

스프링 AOP는 메소드 조인포인트만 지원한다. 핵심기능의(대상객체)메소드가 호출되는
런타임 시점에만 부가기능(어드바이스)을 적용할 수 있다.

알아야할 용어는
프록시
Aspect
Advice
PointCut
JoinPoint
Weaving

필요한 디펜던시는
AspectJ Runtime //버전은 알리아스설정된  aspectJ 버전 사용함
AspectJ Weaver //버전은 알리아스설정된  aspectJ 버전 사용함
AOP Proxy Library cglib2.2

aop설정 방식은 두 가지가 있다.
1. XML 설정 방식
: XML 네임스페이스 및 스키마로케이션을 추가하여 aop 태그를 사용할 수 있게 설정한다.
추가1. xmlns 네임스페이스
xmlns:aop="http://www.springframework.org/schema/aop"
추가2. xsi schemaLocation 추가
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd

servlet-context.xml
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> 를 추가하여 프록시를 설정한다.

root-context.xml
어드바이스 클래스를 bean등록하고
<aop:config> 태그로 aop를 설정한다.
포인트컷 표현식과 해당 표현식을 가져다 쓰기 쉽도록 아이디를 설정한다.
<aop:pointcut expression="execution(   포인트컷표현식  )"  id = "포인트컷 아이디 설정"/>
<aop:aspect ref="bean등록한 어드바이스클래스">
<aop:before(or after or around) method="어드바이스클래스에 설정한 메소드명" pointcut-ref="포인트컷 아이디"/>

->어드바이스, 적용할메소드, 적용할 시점을 설정한 것이다.

 

2. 어노테이션 설정 방식
: 어노테이션 설정방식은 @어노테이션으로 Config 클래스를 설정하고 XML에서 태그로 설정하는 것들을 자바 클래스의 형태로 더 편리하게 설정하게 해주는 것이다. @Aspect로 AOP설정클래스임을 명시하고 @Component로 빈등록한다
다음과 같이 자바 클래스에서 어드바이스, 포인트컷, 적용할 시점을 모두 설정할 수 있다.

@Component
@Aspect
public class AroundLog {

@Pointcut("execution(* com.kh.junspring..*Impl.*(..))")
public void allPointCut() {}

@Around("allPointCut()")
public Object aroundLogs(ProceedingJoinPoint pp) throws Throwable{


Object obj = pp.proceed();

return obj;

 }
}

 

포인트컷 표현식)
반환형 패키지.클래스.메소드(매개변수)
의 구조이다.

* mabb.tistory..*Service.*(..)
->모든반환형 mabb.tistory하위 모든패키지의 Service로끝나는 클래스 하위의 모든 메소드 0개 이상의 모든 매개변수
: 매개변수의 ..은 0개이상의 모든타입, *은 1개의 모든타입을 뜻한다. 패키지경로에 .마침표를 하나 더 찍으면 하위의 모든 패키지를뜻한다.

 

★★★★
around로 적용 시 조인포인트의 proceed()메소드를 꼭 적어주어야 한다.
이 proceed()가 가로채서 실행하는 타겟 메소드인 것이다.
이 proceed() 메소드의 반환형은 object인데 
원래의 타겟 메소드가  반환형이 있을 경우에는 
꼭 object를 반환해주어야 타겟팅된 원래의 메소드가 정상작동한다.

타겟메소드를 가로채서 around로 설정한 advice 코드 안에서 proceed()라는 이름으로
대리 실행을 시킴으로써 그 앞뒤를 구분하여  공통 코드를 작성할 수 있는 것이다.

proceed의 반환값 object를 반환해주지 않으면
제대로 동작하지 않는다

proceed는 그 자체로 그 메소드를 대행하는 것이었다.

 

배운것을 토대로 홈컨트롤러에 있는 Logger를 가져다 로깅기능을 추가해보았다.

 

배운것을 토대로 ServiceImpl하위 모든 메소드 실행 시 반환값을 확인할 수 있는 로거 만들어보기)

logger.info( pp.getSignature());
Object object = pp.proceed();
logger.info("반환값 " + object);

이런식으로 해주면 어떤 메소드가 실행되어서 어떤 값을 반환했는지
확인할 수 있다. 포인트컷은 ServiceImpl 하위의 모든 메소드로 설정하였다.

반응형