-
AOPSpring/스프링가링가링 2022. 11. 9. 02:31
[Spring] 스프링 AOP (Spring AOP) 총정리 : 개념, 프록시 기반 AOP, @AOP (tistory.com)
AOP : Aspect Oriented Programming
- 관점 지향 프로그래밍
- 취지: 흩어진 관심사를 Aspect로 모듈화하고 핵심적인 비즈니스 로직에서 분리하여 재사용하는 것
• Aspect : 흩어진 관심사를 모듈화한 것
• Target : Aspect를 적용하는 곳 (클래스, 메서드 등)
• Advice : 실질적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가기능을 담은 구현체
• JointPoint : Advice가 적용될 위치. 메서드 진입 지점, 생성자 호출 시점, 필드에서 꺼내올 때 등 다양한 시점에 적용 가능
• PointCut : JointPoint의 상세한 스펙을 정의한 것. Adivce가 실행될 지점을 더 구체적으로 알 수 있음
스프링 AOP 특징
• 프록시 패턴 기반의 AOP 구현체, 프록시 객체를 쓰는 이유는 접근 제어 및 부가기능을 추가하기 위함
• 스프링 빈에만 AOP 적용 가능
• 모든 AOP 기능을 제공하는 것이 아닌 스프링 IoC와 연동하여 중복 코드 등의 문제에 대한 해결책을 지원하는 것이 목적
build.gradle 파일에 AOP 사용을 위한 의존성 추가
dependencies { implementation 'org.springframework.boot:spring-boot-starter' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'org.springframework.boot:spring-boot-starter-aop' //AOP 의존성 추가 }
package com.example.springggaop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Component @Aspect public class AOPTmp { @Around("execution(* com.example..*.EventService.*(..))") public Object logPerf(ProceedingJoinPoint pjp) throws Throwable { long begin = System.currentTimeMillis(); Object retVal = pjp.proceed(); System.out.println(System.currentTimeMillis() - begin); return retVal; } }
@Around : 타겟 메서드를 감싸서 특정 Advice를 실행한다는 의미
execution(* com.example..*.EventService.*(..))
: com.example 아래의 패키지 경로의 EventService 객체의 모든 메서드에 해당 Aspect를 적용
package com.example.springggaop.service; public interface EventService { void createEvent(); void publishEvent(); void deleteEvent(); }
package com.example.springggaop.service; import org.springframework.stereotype.Component; @Component public class EventServiceConfig implements EventService{ @Override public void createEvent() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Created an event"); } @Override public void publishEvent() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Published an event"); } @Override public void deleteEvent() { System.out.println("Delete an event"); } }
package com.example.springggaop.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Service; @Service public class AppRunner implements ApplicationRunner { @Autowired EventService eventService; @Override public void run(ApplicationArguments args) throws Exception { eventService.createEvent(); eventService.publishEvent(); eventService.deleteEvent(); } }
실행결과 package com.example.springggaop; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS) public @interface PerLogging { }
@Component @Aspect public class AOPTmp { @Around("@annotation(PerLogging)")
위와 같이 특정 어노테이션이 붙은 포인트에서만 Aspect를 실행할 수 있는 기능도 있음
createEvent() 와 deleteEvent() 에만 @PerLogging을 붙여주면,
실행결과 위와 같이 두 메소드에서만 Aspect가 실행됨
@Around("bean(EventServiceTmp)")
위와 같이 하면 스프링 빈의 모든 메서드에 적용된다.
@Around말고도 타겟 메서드의 Aspect 실행 시점을 지정할 수 있는 어노테이션들이 많음
- @Before : 메소드 실행 전
- @After : 메소드 실행 후
- @AfterReturning : 메소드 정상 실행 후
- @AfterThrowing : 메소드 예외 발생 후
마법의 코드, 어드바이스 | Moon`s Development Blog (gmoon92.github.io)
Advice
- 타깃 오브젝트에 적용하는 부가기능을 담은 오브젝트
- Advisor: PointCut + Advice
📎 어드바이스의 동작
- Spring을 포함한 대부분의 AOP 프레임워크는 사용자의 요청을 인터셉터하고, 지정된 어드바이스를 모델링함
- => 조인 포인트 주변에 지정된 어드바이스 코드가 결합된 상태가 됨
- 이 상태가 체인같이 보여서 어드바이스 체인이라고 하는 것
- 실제 런타임 시, 어드바이스 체인이 유지된 상태로 결합한 코드가 실행됨
- => 어드바이스를 구현할 때, 어느 조인 포인트와 결합할지 명시해주어야 함
📎 어드바이스의 종류
- Before
- 비즈니스 메소드 실행 전 동작
- After Running
- 비즈니스 메소드가 성공적으로 리턴되면 동작
- 메소드 내부에 리턴값이 존재하는 경우만!
- After Throwing
- 비즈니스 메소드 실행 중, 예외가 발생하면 동작
- After
- 비즈니스 메소드 실행 중, 예외가 발생하면 무조건 동작
- Around
- 메소드 호출 자체를 가로채서 비즈니스 메소드 실행 전과 후에 모두 처리할 로직을 삽입 가능
03. Aspect 작성 - 2 (tistory.com)
'Spring > 스프링가링가링' 카테고리의 다른 글
JPA 지연로딩 사용시 N+1 문제 (0) 2022.10.06