톰캣-필터-디스패쳐서블릿-(각각의)컨트롤러-서비스-리포지토리-퍼시스턴스컨텍스트
톰캣에서 리퀘스트(요청정보) 리스펀스(응답정보) 생성
(문자열로 오면 파싱해서 리퀘스트로 만듬)
디스패쳐서블릿 :
1. 주소분석(리플렉션으로 컨트롤러의 @어노테이션을 찾음)
2. 바디데이터 파싱(post나 put요청은 바디데이터가 있으니까)
3. 마임타입:application/json
컨트롤러에서 찾은 메서드의 매개변수를 리플렉션으로 분석함
매개변수에 @RequestBody String이면 그냥 json문자열 그대로 넣음
@RequestBody 클래스(dto)라면 필드에 바인딩해줌
AOP
관점 지향 프로그래밍
리플렉션으로
공통 기능을 만들어놓고
리플렉션으로 끼워넣을곳을 분석해서 알맞게 끼워넣음
스프링 리플렉션 제어권 나에게 없음 : 대신 AOP
공통 기능 (관점에 따라 다르게 동작함)
관심사 분리 (핵심로직만 집중할 수 있게)
인터셉터는 모두 동일하게 동작함
필터 인터셉터 aop 차이
https://carnival.tistory.com/77
인터셉터는 매개변수 분석이 안됨
AOP 주요 개념
Aspect : 흩어진 관심사를 모듈화 한 것
Target : Aspect를 적용하는 곳 (ElementType 등)
Advice : 실질적인 부가기능을 담은 구현체 (@Before, @After, @AfterReturning, @AfterThrowing, @Around)
JointPoint : Advice가 적용될 위치, 끼어들 수 있는 지점.
PointCut : JointPoint의 상세한 스펙을 정의한 것.
@Valid
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody @Valid UserRequest.LoginDTO requestDTO, Errors errors) {
...
}
@Aspect
@Component
public class ValidAdvice {
// 별칭 등록
@Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
public void postMapping(){}
// 공통 기능
@Before("postMapping()") // @PostMapping어노테이션이 붙은 메서드 전에 실행됨
public void checkValid(JoinPoint jp){ // JoinPoint 객체는 AOP에서 사용되며, 현재 실행 중인 메서드 정보를 제공
Object[] args = jp.getArgs(); // 현재 실행 중인 메서드의 매개변수를 가져옴
for (Object arg : args) {
if(arg instanceof Errors){ // 메서드의 매개변수 중에서 Errors 타입의 객체를 찾는다
Errors errors = (Errors) arg;
if(errors.hasErrors()){ // errors 객체가 유효성 검사 오류가 있는지 확인
List<FieldError> fieldErrors = errors.getFieldErrors(); // FieldError는 개별 필드에 대한 오류 정보
throw new Exception400(
fieldErrors.get(0).getDefaultMessage()+":"+fieldErrors.get(0).getField()
);
}
}
}
}
}
BindingResult는 인터페이스고, Errors 인터페이스를 상속받고 있다.
Errors 인터페이스는 단순한 오류 저장과 조회 기능을 제공한다.
BindingResult는 여기에 더해서 추가적인 기능들을 제공한다. (ex. addError())