일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 1300번
- 2156번
- SerialDate 리펙터링
- 9장
- 가장 긴 증가하는 부분 수열2
- java의 정석
- 10830번
- Design Patterns
- 클린코드
- 2166번
- 자바의 정석
- Spring
- Adapater Pattern
- 2206번
- 17장
- 백준
- Dxerr.h
- DxTrace
- springboot
- 코딩 테스트
- 냄새와 휴리스틱
- 11286번
- 1043번
- 코딩테스트
- java
- 프로그래머스
- Design Pattern
- programmers
- BOJ
- 11758번
- Today
- Total
Don't give up!
[SpringBoot] Spring과 AOP 본문
관점 지향 프로그래밍(Aspect-Oriented Programming, AOP)
AOP는 각 기능들에 흩어져 있는, 그러나 독립적으로 분리하기 어려운 부가 기능들을 모듈화하는 프로그래밍 기법입니다.
공통된 부가 기능들을 재사용함으로써 애플리케이션 전체에 흩어진 공통 기능을 하나의 장소에서 관리할 수 있고 서비스 모듈로 하여금 다른 모듈을 신경쓰지 않도록 한다는 장점을 가지고 있습니다.
왜 필요한가?
객체지향 프로그래밍(OOP)에서는 단일 책임 원칙(Single Responsibility Principle, SRP)에 따라 하나의 클래스는 하나의 책임만 가져야 하며 개방 폐쇄 원칙(Open-Closed Principle, OCP)에 의하여 확장에는 열려 있으나 변경에는 닫혀 있어야 합니다.
public class UserService {
private UserRepository repository;
public List<User> getUsers() {
long start = System.currentTimeMillis();
List<User> users = repository.findAll();
long end = System.currentTimeMillis();
System.out.println("수행 시간 : " + (end - start));
return users;
}
}
public class BoardService {
private BoardRepository repository;
public List<Board> getBoards() {
long start = System.currentTimeMillis();
List<Board> boards = repository.findAll();
long end = System.currentTimeMillis();
System.out.println("수행 시간 : " + (end - start));
return boards;
}
}
그러나 위와 같은 코드의 경우 하나의 함수가 2개 이상의 행동을 하고 코드가 중복되어 있습니다.
상속을 통해 이러한 문제들을 해결할 수도 있겠으나 여러 클래스에 걸쳐 중복되는 부가 기능들이 2개 이상인 경우 이를 해결하기 어렵습니다.
AOP에서는 이러한 부가기능들을 관점(Aspect)로 정의하고 모듈화함으로써 문제를 해결합니다.
스프링 AOP
스프링은 @Aspect 어노테이션으로 부가 기능 모듈을 정의할 수 있으며 다음의 특징을 갖고 있습니다.
- 스프링 Bean에만 AOP를 적용할 수 있다.
- Proxy 패턴 기반의 AOP 구현체이다. (접근 제어 및 부가기능을 추가하기 위함)
@Target(ElementType.MEHTOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogPerformanceTime{
}
@Component
@Aspect
public class PerformanceAspect {
@Around("@annotation(LogPerformanceTime)")
public Object logPerformanceTime(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
try {
long start = System.currentTimeMillis();
result = joinPoint.proceed();
long end = System.currentTimeMillis();
System.out.println("수행 시간 : "+ (end - start));
} catch (Throwable throwable) {
System.out.println("Exception");
}
return result;
}
}
public class UserService {
private UserRepository repository;
@LogPerformanceTime
public List<User> getUsers() {
List<User> users = repository.findAll();
return users;
}
}
public class BoardService {
private BoardRepository repository;
@LogPerformanceTime
public List<Board> getBoards() {
List<Board> boards = repository.findAll();
return boards;
}
}
부가기능 모듈(Aspect) PerformanceAspect는 애너테이션 또는 XML로 빈 등록을 하여 Spring에 정의할 수 있습니다.
Aspect의 부가기능이 적용될 곳(Target)은 @Around와 같이 부가기능에 붙은 애너테이션에 PointCut 표현식을 넣어 선언합니다.
@Around 애너테이션은 AOP의 Advice입니다.
Aspect가 실행될 위치를 알리고 언제 실행될 것인지를 애너테이션 자체로서 정의합니다.
애너테이션 | 실행되는 위치 |
@Before | Target 메서드가 호출되기 전에 Advice 기능을 수행 |
@After | Target 메서드의 결과에 관계없이 완료되면 Advice 기능을 수행 |
@AfterReturning | Target 메서드가 성공적으로 결과값이 반환된 후 기능을 수행 |
@AfterThrowing | Target 메서드가 예외를 던지면 기능을 수행 |
@Around | Target 메서드 전/후에 기능을 수행 |
Advice가 수행될 Target은 코드와 같이 애너테이션으로 지정하는 방법, PointCut 표현식으로 클래스 혹은 메소드를 직접 지정하는 방법이 있습니다.
지정자 | 설명 |
args() | 메서드의 인자가 해당 타입인 경우 |
@args() | 메서드의 인자가 해당 어노테이션 타입을 갖는 경우 |
execution() | 해당 경로의 패키지, 클래스 또는 메소드 |
within() | 해당 패키지 내 클래스와 인터페이스가 가진 메소드 |
this() | Target 메서드가 지정된 빈 타입의 인스턴스인 경우 |
target() | 지정된 (빈 타입이 아닌) 타입의 인스턴스인 경우 |
@target() | 객체의 클래스에 지정된 타입의 어노테이션이 있는경우 |
@annotation | 지정된 어노테이션이 Target 메서드에 지정된 경우 |
출처
[Spring] 스프링 AOP (Spring AOP) 총정리 : 개념, 프록시 기반 AOP, @AOP (tistory.com)
'Spring Boot' 카테고리의 다른 글
[Spring Boot] Bean 등록 (0) | 2021.08.04 |
---|---|
[Spring Boot] SpringApplication의 실행과정 (0) | 2021.08.02 |