AOP란? -> 관점 지향 프로그래밍의 약자
=공통되는 부분을 따로 빼내어 필요한 시점에 해당코드를 추가해주는 기술
ex)컨트롤러 -> 서비스 이동시마다 println 을 실행한다면?
1. Advice : 공통되는 부분을 따로 빼내어 작성하는 메소드
2. JoinPoint : Advice가 적용될 수 있는 모든 관점(시점) -> 매우많음
3. Pointcut : JoinPoint 중 실제 Advice를 적용할 부분
4. Weaving : 그 시점에 공통 코드를 끼워넣는 작업
(컴파일 시 , 클래스 로딩 시 , 런타임 시 ) 가능
*Aspect = Advice + Pointcut : 실제동작코드 + 실제 적용된 부분 을 작성한클래스
=> 부가기능(로깅, 보안, 트랜잭션 등)을 나타내는 공통 관심사에 대한 추상적인 명칭)
=> 여러 객체에 공통으로 적용되는 부가기능을 작성한 클래스를 나타냄
=> 독립적인 요소로 구분해 내서 부가기능을 런타임 시 필요한 위치에 동적으로 참여하게 할 수 있다
Advice 시점에 따라
Before Advice | JoinPoint 앞에서 실행 |
Around Advice | JoinPoint 앞과 뒤에서 실행 |
After Advice | JoinPoint 호출이 리턴되기 직전에 실행 |
After Returning Advice | JoinPoint 메소드 호출이 정상적으로 종료된 후에 실행 |
After Throwing Advice | 예외가 발생했을 때 실행 |
*Proxy : 대상 객체에 Advice가 적용된 후 생성되는 객체
*Target Object : Advice를 삽입할 대상 객체
스프링은 대상 객체에 대한 프록시를 만들어 감싸서 대상 객체를 호출할 때 먼저 호출되서
Advice 로직을 처리한 후 대상 객체를 다시 호출한다.
[ AOP 구현 ] - *애너테이션 방식*
Spring pom.xml에 이미 aspectj 가 포함되어있음
+ 좀 더 쉬운 구현을 위한 Weaver 추가
***MVN Repository => Aspectj Weaver 추가
1. 해당 클래스에 @Aspect -> 공통 관심사가 작성된 클래스임을 명시
+(Advice, Pointcut 작성되어 있어야 함)
+@Conmonent 추가해 런타임 중 Advice코드가 동적으로 추가될 수 있도록 bean 등록
***servlet-context에서 namespace - aop 체크 + <aop:aspectj-autoproxy/> 작성 필요 ***
2. 수행할 메소드 + @Before / @After ...
*@Before("Pointcut") : Pointcut으로 지정된 메소드가 수행되기 전에 Advice 수행
**Pointcut 작성법 3가지
1) 직접
@Before("execution( * a.b.c..*Controller.*(..))")
작성식 : execution [접근제한자] +리턴타입 + 패키지경로명 + 클래스(*C : 모든 컨트롤러) + 메서드( *(..) : 모든 메서드)
-접근제한자는 생략가능/ *: 모든 리턴타입 의미 / .. : 하위 모든 패키지 or 0개 이상의 매개변수-
2) Pointcut이 작성된 메소드명을 작성
3) 타 클래스에 작성된 Pointcut 메소드를 작성
3. 메소드 작성
//@Before(직접작성)
@Before("PointcutCollection.controllerPointcut()")
public void controllerLog(JoinPoint jp) {
logger.info("테스트");
jp.getArgs() : 수행되는 메소드의 모든 매개변수를 배열로 얻어옴
jp.getTarget() : 타겟이 된 객체를 얻어온다
jp.getSignature() : 수행되려는 메소드 선언부를 얻어옴
{
-매개변수로 입력한 JoinPoint : 부가 기능 메소드를 제공하는 인터페이스
3-1 Pointcut을 모아둘 클래스
public class PointcutCollection {
@Pointcut("execution( 식 작성 )
public void controllerPointcut(){}
@Pointcut("execution( 식 작성2 )
public void servicePointcut(){}
}
++ Around 사용 -- 앞뒤 모두 아우르는 관점 ex) 러닝타임계산
@Aspect // Advice + Pointcut 공통 관심사가 작성된 클래스임을 명시
@Component
public class AroundAspect {
//slf4j import
private Logger logger = LoggerFactory.getLogger(AroundAspect.class);
//Around : 전처리, 후처리를 모두 해결하고자 할 때
//ProceedingJoinPoint를 매개변수 필수 사용
//(Proceeding: 진행)
//-> proceed() 메소드 사용 가능: 해당 메소드를 기준으로 Before, After 나뉨
@Around("PointcutCollection.serviceImplPointcut()")
public Object aroundLog(ProceedingJoinPoint pp) throws Throwable {
// 클래스명
String className = pp.getTarget().getClass().getSimpleName(); // 대상 객체의 간단한 클래스명(패키지명 제외)
// 메소드명
String methodName = pp.getSignature().getName(); // 대상 객체 메소드의 정보 중 메소드명을 반환.
String str = "";
str += "[Service]" + className + "-" + methodName + "()";
long startMs = System.currentTimeMillis(); // 서비스 시작 시의 ms 값
//구분기준
Object obj = pp.proceed();
long endMs = System.currentTimeMillis(); // 서비스 종료 시의 ms 값
//걸린시간
str+= "[Running Time]" +(endMs-startMs) + "ms";
//서비스 수행 시 사용된 파라미터
str+= "[Param]" + Arrays.toString(pp.getArgs());
logger.debug(str);
//proceed 반환값을 무조건 리턴
return obj;
}
}
'개발자로 업그레이드 되자 > SpringMVC' 카테고리의 다른 글
Spring - 쿠키 전송(ex 로그인 시 아이디 저장) (0) | 2022.02.02 |
---|---|
Spring 스케줄러 (0) | 2022.01.14 |
SPRING MVC에서 Mybatis 활용 (0) | 2022.01.13 |
스프링 MVC - 이미지 업로드 / 파라미터 사용 DB삽입 (0) | 2022.01.11 |
스프링MVC - 트랜잭션 및 예외처리 (0) | 2022.01.06 |