코딩하는 오징어
Spring boot @Annotation으로 AOP적용하기 본문
AOP를 적용하기 전에 AOP가 무엇인지에 대해 먼저 알아보자.
AOP란 Aspect Oriented Programming의 약자로써 바라보는 관점을 기준으로 프로그래밍하는 기법을 말한다. 문제를 해결하기 위해 핵심 관심 사항과 전체에 적용되는 공통 관심 사항을 기준으로 프로그래밍 함으로써 공통 모듈을 여러 코드에 쉽게 적용할 수 있도록 도와준다.
AOP의 주요 용어
Joinpoint : Advice를 적용 가능한 지점을 의미. 메서드 호출, 필드 값 변경등이 Joinpoint에 해당
Pointcut : Joinpoint의 부분 집합으로서 실제로 Advice가 적용되는 Joinpoint를 나타낸다. 스프링에서는 정규 표현식이나 AspectJ의 문법을 이용하여 Pointcut을 정의할 수 있음.
Advice : 언제 공통 관심 기능을 핵심 로직에 적용할 지를 정의. 예를 들어, '메서드를 호출하기 전(언제)'에 '트랜잭션 시작'(공통기능) 기능을 적용한다는 것을 정의 하고있음.
Weaving : Advice를 핵심 로직 코드에 적용하는 것을 weaving이라고 한다. 즉, 공통 코드를 핵심 로직 코드에 삽입하는 것이 weaving이라고 함.
Aspect : 여러 객체에 공통으로 적용되는 기능을 Aspect라고 한다. 트랜잭션이나 보안등이 Aspect의 좋은 예임.
스프링에서의 AOP
스프링은 자체적으로 프록시 기반의 AOP를 지원하고 있다. 따라서 스프링 AOP는 메서드 호출 Joinpoint만을 지원한다. (필드 값 변경과 같은 Joinpoint를 사용하고 싶다면 AspectJ와 같이 다양한 Joinpoint를 지원하는 AOP도구를 사용해야함)
스프링은 세가지 방식으로 AOP를 구현할 수 있도록 하고 있다.
- XML 스키마 기반의 POJO 클래스를 이용한 AOP구현
- AspectJ에서 정의한 @Aspect 애노테이션 기반의 AOP구현
- 스프링 API를 이용한 AOP구현
package com.finder.genie_ai.aops;
import com.finder.genie_ai.exception.UnauthorizedException;
import com.finder.genie_ai.redis_dao.SessionTokenRedisRepository;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class CheckSessionValid {
private SessionTokenRedisRepository sessionTokenRedisRepository;
@Autowired
public CheckSessionValid(SessionTokenRedisRepository sessionTokenRedisRepository) {
this.sessionTokenRedisRepository = sessionTokenRedisRepository;
}
@Pointcut("execution(public * com.finder.genie_ai.controller.ShopController.*(..))")
public void controllerClassMethods() {}
@Before(value = "controllerClassMethods()")
public void checkSessionValid(JoinPoint joinPoint) {
String token = (String)joinPoint.getArgs()[0]; //JoinPoint클래스를 이용하여 타켓 메서드의 파라미터를 가로챌 수 있다.
System.out.println(token);
if (!sessionTokenRedisRepository.isSessionValid(token)) {
throw new UnauthorizedException();
}
JsonElement element = new JsonParser().parse(sessionTokenRedisRepository.findSessionToken(token));
System.out.println(element.getAsJsonObject());
}
}
헤더에 토큰값을 보내면 API 진입전에 토큰 값을 검사하여야한다. 결과를 보면 토큰 값을 redis에서 잘 확인해서 데이터를 잘 뽑아 온것을 확인할 수 있다.
Redis에 저장되어있는 토큰값에 해당하는 value값도 잘 뽑아와서 로그를 뿌려주는 것도 잘된다.
이 블로그가 AOP에대한 설명이 잘되어있다.
'Framework > Spring' 카테고리의 다른 글
intellij에서 Spring 4 초기 환경 세팅에서 디비연동까지 한 번에 하기 (Maven & Mysql & Mybatis) (7) | 2018.03.09 |
---|---|
Spring 4 하나 이상의 Dispatcher Servlet 설정하기 (1) | 2018.03.07 |
Spring 4 mvc에서 Restful API (0) | 2018.03.06 |
@Bean 과 @Component의 차이 (1) | 2018.02.27 |
Spring에서 Redis ZSET구조 이용하기 (0) | 2018.02.26 |