정의
스프링 프레임워크에서 제공하는 기능 중 하나
핵심 비즈니스 로직에서 부가적인 관심사를 분리하여 코드의 모듈성 향상, 재사용성 향상,
코드의 복잡도를 줄이는데 목적을 둠
메소드안에 핵심적인 비즈니스 로직과 같이 작성하는 것이 아닌, 따로 모듈화 하여 여러객체에 공통적으로 사용할 수 있게하는 코드
핵심 개념
관심사의 분리 - 핵심 비즈니스 로직과 부가적인 기능을 분리하여 코드의 모듈성 향상
재사용성 및 유지보수성 - 부가적인 기능을 애스팩트로 모듈화하여 재사용 가능하고, 유지보수성 향상
포인트 컷 : 부가적인 기능이 적용될 지점을 명시적으로 정의, 필요할 때만 적용
주요 용어
- @Aspect : 해당 클래스를 부가적인 기능을 정의한 모듈
- JoinPoint : Aspect가 적용될 수 있는 애플리케이션 실행 지점
- Advice : Aspect의 실제 동적을 정의
- @Befro, @After, @Around : 조인 포인트가 실행되기 전, 실행 후, 실행 전후 모두 실행하겠다.
- @Pointcut : Aspect가 적용될 조인 포인트를 선택하는 표현식, 조인 포인트를 필터링하여 특정 메서드나 클래스 등에 Aspect를 적용할 수 있다.
- Weaving : Aspect를 애플리케이션의 실제 코드에 적용하는 과정
예제
import com.example.blog._core.error.ex.Exception400;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
@Aspect
@Component
public class MyValidationAspect {
@Before("@annotation(org.springframework.web.bind.annotation.PostMapping)")
// Around는 JoinPoint가 아니라 ProceedingJoinPoint 사용
public void validationCheck(JoinPoint jp) throws Throwable {
Object[] args =jp.getArgs();
for(Object arg : args) {
if(arg instanceof Errors) {
Errors errors = (Errors) arg;
if (errors.hasErrors()) {
String errMsg = errors.getFieldErrors().get(0).getField() +" : "+errors.getFieldErrors().get(0).getDefaultMessage();
throw new Exception400(errMsg);
}
}
}
}
}
@Data //getter,setter, toString
public static class SaveDTO{
@NotBlank(message = "title을 입력해주세요")
private String title;
@NotBlank(message = "content를 입력해주세요.")
private String content;
public Board toEntity(){
Board board = new Board(null,title, content, null);
return board;
}
}
import com.example.blog._core.error.ex.Exception400;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import java.util.List;
// Controller의 책임 : 외부 클라이언트의 요청을 받고 그 요청에 대한 응답을 함
@Controller
@RequiredArgsConstructor
public class BoardController {
private final BoardService boardService;
@PostMapping("/board/save")
public String saveV2(@Valid BoardRequest.SaveDTO saveDTO, Errors errors) {
boardService.게시글쓰기(saveDTO);
return "redirect:/";
}
@PostMapping("/board/{id}/update")
public String update(@PathVariable("id") int id, @Valid BoardRequest.updateDTO updateDTO, Errors errors) {
boardService.게시글수정(id,updateDTO);
return "redirect:/";
}
}
설명
AOP를 사용한 유효성 검사
- MyValidationAspect 클래스는 @PostMapping 어노테이션이 달린 메서드들에서 Errors 객체를 검사
- 오류가 있을 경우 사용자 정의 예외(Exception400)를 던짐
- 유효성에 대한 에러 상황에 대한 일관적 처리 가능
Share article