스프링 코어 중 다른 하나인 DIxAOP 컨테이너의 AOP에 대해 알아보기
- DI 컨테이너란 오브젝트 사이에 밀접한 의존 관계를 가지지 않게 하고, 인터페이스에 의한 약한 결합을 쉽게 만들어 소프트웨어의 컴포넌트화를 촉진하며, 오브젝트의 생명 주기를 관리할 수 있게 하는 것
- DI 컨테이너만으로는 온전한 아키텍처를 개발할 수 없음
- AOP가 있으면 로깅이나 트랜잭션 등의 처리를 따로 관리할 수 있게 구현하는 기술
3.1 AOP란
- AOP란 업무 등 특정 책임이 있는 클래스 같이 본질적이지 않은 처리들을 밖으로 꺼내는 기술
3.1.1 AOP 용어
애스펙트(Aspect)
- 횡단 관심사의 동장과 그 횡단 관심사를 적용하는 소스 코드상의 포인트를 모은 것
어드바이스(Advice)
- 조인 포인트에서 실행되는 코드.
- 로그 출력이나 트랜잭션 관리 등의 코드.
조인 포인트(Join Point)
- 어드바이스가 실행하는 동작을 끼워 넣을 수 있는 때를 말함.
- 조인 포인트는 개발자가 고려해서 만들어 넣을 수 없는 AOP의 사양.
- 메소드가 호출될 때와 메소드가 원래 호출한 곳으로 돌아갈 때가 어드바이스를 끼워 넣을 수 있는 조인 포인트.
포인트컷(Pointcut)
- 조인포인트와 어드바이스의 중간에 있으면서 처리가 조인 포인트에 이르렀을 때 어드바이스를 호출할 지 선별함.
- 조인포인트의 상세한 스펙을 정의한 것.
3.1.2 스프링이 제공하는 어드바이스
- 스프링이 제공하는 어드바이스
어드바이스의 형태 | 설명 |
Before | 조인트 앞에서 실행할 어드바이스 |
After | 조인포인트 뒤에서 실행할 어드바이스 |
AfterReturning | 조인포인트가 완전히 정상 종료한 다음 실행되는 어드바이스 |
Around | 조인포인트 앞뒤에서 실행되는 어드바이스 |
AfterThrowing | 조인포인트에서 예외가 발생했을 때 실행되는 어드바이스 |
3.1.3 프록시를 이용한 AOP
- 프록시 기반의 AOP 구현체이다. 프록시 객체를 사용하는 이유는 접근 제어 및 부가 기능을 추가하기 위해서이다.
- 스프링 빈에만 AOP를 적용할 수 있다.
- 모든 AOP 기능을 제공하는 것이 목적이 아니라, 스프링 IoC와 연동하여 엔터프라이즈 애플리케이션에서 가장 흔한 문제(중복코드, 프록시 클래스 작성의 번거로움, 객체 간 관계 복잡도 증가 등등…)를 해결하기 위한 솔루션을 제공하는 것이 목적.
3.2 어노테이션을 이용한 AOP
- 스프링의 AOP를 사용하기 위한 방법은 3가지
1. Bean 정의 파일에 설정
2. JavaConfig에 작성
3. 어노테이션 작성
https://devhooney.tistory.com/9?category=1052447
- 상단 게시물에서 작성한 Product로 예제를 재사용 함.
- AOP의 적용 대상은 ProductDao의 findProduct 메소드
@Aspect
@Component
public class MyFirstAspect {
@Before("execution(* findProduct(String))")
public void before() {
// 메소드 시작 시 동작하는 어드바이스
System.out.println("Hello Before");
}
@After("execution(* findProduct(String))")
public void after() {
// 메소드 종료 후 동작하는 어드바이스
System.out.println("Hello After");
}
@AfterReturning(value="execution(* findProduct(String))", returning="product")
public void afterReturning(Product product) {
// 메소드 호출이 예외를 내보내지 않고 종료했을 때 동작하는 어드바이스
System.out.println("Hello AfterReturning");
}
@Around("execution(* findProduct(String))")
public Product around(ProceedingJointPoint pjp) throws Throwable {
// 메소드 호출 전후에 동작하는 어드바이스
System.out.println("Hello Around Before");
Product p = (Product)pjp.procced();
System.out.println("Hello Around After");
return p;
}
@AfterThrowing(value="execution(* findProduct(String))", throwing="ex")
public void afterThroing(Throwable ex) {
// 메소드 호풀이 예외를 던졌을 때 동작하는 어드바이스
System.out.println("Hello Throwing);
}
}
- 클래스 선언 앞에 애스팩트임을 나타내는 @Aspect를 붙임
- 결과
Hello Before
Hello Around before
Hello After
Hello Around After
Hello AfterReturning
Product [name=공책, price=100]
3.2.1 포인트컷 기술 방법
- 어노테이션 괄호 안에 "execution(* findProduct(String))" 형식으로 기술
- execution 기본 구문
- "메소드의 수식자(public 혹은 private)"나 "throws 예외"는 생략 가능
- 메소드의 반환값형, 패키지와 클래스명, 인터페이스명에는 와일드카드 (*)를 이용 가능
- "*"는 "."(패키지 구분 문자)와 일치하지 않으므로 복수 패키지와 일치시키려면 ".."를 사용
- 메소드의 인수에 ".."를 기술하면 모든 인수와 일치시킬 수 있음
'개발 > Java & Kotlin' 카테고리의 다른 글
[Spring] 스프링 AOP (2) (0) | 2022.07.04 |
---|---|
[Java] 람다와 스트림(5) (0) | 2022.07.04 |
[Java] 람다와 스트림(4) (0) | 2022.07.01 |
[Java] 람다와 스트림(3) (0) | 2022.06.30 |
[Spring] 스프링 DI (2) (0) | 2022.06.29 |