*AOP를 배우기 전 중요한 기본 개념*
●핵심 기능(Core Concerns) : 객체가 제공하는 고유의 기능(업무 로직 등을 포함)
●부가 기능(CROSS-CUTTING CONCERNS) : 핵심 기능을 보조하기 위해 제공되는 기능으로 핵심 기능과 함께 사용됨. 예)로깅,보안,트랜잭션 등
●Aspect : 부가 기능을 정의한 코드인 어드바이스(Advice)와 어드바이스를 어디에 적용할지 결정하는 포인트컷(PointCut)을 합친 개념 (Advice + PointCut ⇒ Aspect)
**AOP가 필요한 이유에 대해**
●객체 지향 프로그래밍(OOP)방식의 프로그래밍을 했을 때 여러 곳에서 공통적으로 사용되는 부가 기능의 중복 코드가 발생함
●중복되는 부가 기능에 수정 및 삭제가 필요하게 되면 사용되는 모든 곳에 수정 및 삭제 동작을 해줘야함
●관심 지향 프로그래밍(AOP)은 OOP 방식의 불필요한 반복을 해결하기 위한 방법임
2.AOP(Aspect Oriented Programming) |
2-1.AOP 용어
(1)Aspect
-여러 객체에 공통으로 적용되는 기능(공통 기능)
-어드바이스 + 포인트컷을 모듈화하여 애플리케이션에 포함되는 횡단 기능
(2)Join point
-AOP를 적용할 수 있는 모든 지점
-클래스 초기화, 객체 인스턴스화, 메소드 호출, 필드 접근, 예외 발생과 같은 애플리케이션 실행 흐름에서의 특정 포인트를 의미
-횡단 관심은 조인포인트 전/후에 AOP에 의해 자동으로 추가됨
-애플리케이션에 새로운 동작을 추가하기 위해 조인포인트에 관심 코드(aspect code)를 추가할 수 있음
(3)Advice
-Join point에서 수행되는 코드를 의미
-Aspect를 언제 핵심 코드에 적용할 지를 정의
-위 그림처럼 메소드를 호출하기 전에 각 상세 정보와 모든 메소드를 로그로 남기기 위해 메소드 시작 전의 포인트인 조인포인트 S를 선택함
(4)Pointcut
-조인 포인트 중에서 어드바이스가 적용될 위치를 선별하는 기능
-AspectJ 표현식을 사용해서 지정
(5)Weaving
-포인트컷으로 결정한 타겟의 조인 포인트에 어드바이스를 적용하는 것(Advice를 핵심 코드에 적용하는 것을 의미)
-핵심 기능 코드에 영향을 주지 않고 부가 기능을 추가 할 수 있음
(6)AOP 프록시(proxy)
-AOP 기능을 구현하기 위해 만든 프록시 객체
-스프링에서 AOP 프록시는 JDK 동적 프록시 또는 CGLIB 프록시
*서버와 클라이언트 사이에 중계기로서 대리로 통신을 수행하는 것을 가리켜 '프록시', 그 중계 기능을 하는 것을 프록시 서버라고 부름
(7)Target
-핵심 기능을 담고 있는 모듈로 타겟은 부가기능을 부여할 대상
-Adivce를 받는 객체이고 포인트컷으로 결정됨
(8)Advisor
-하나의 어드바이스와 하나의 포인트 컷으로 구성됨
-스프링 AOP에서만 사용되는 특별한 용어
2-2.타입별 Advice
-Advice는 기본적으로 순서를 보장하지 않음
-Advice 종류
(1)Before
-조인 포인트 실행 이전에 실행
-타겟 메서드가 실행되기 전에 처리해야할 필요가 있는 부가 기능을 메서드 호출 전에 실행
-일반적으로 리턴타입이 void임(리턴 값을 갖더라고 실제 Advice 적용 과정에 아무 영향이 없음)
-메서드에서 예외를 발생시킬 경우 대상 객체의 메서드가 호출되지 않게 됨
1
2
3
4
|
@Before("hello.aop.order.aop.Pointcuts.orderAndService()")
public void doBefore(JoinPoint joinPoint) {
log.info("[before] {}", joinPoint.getSignature());
}
|
cs |
●작업 흐름을 변경할 수 없음
●메서드 종료 시 자동으로 다음 타겟이 호출됨.(예외가 발생하면 다음 코드는 호출되지 않음)
(2)After returning
-조인 포인트가 정상 완료 후 실행
-메서드가 예외 없이 실행된 이후에 공통 기능을 실행함
1
2
3
4
|
@AfterReturning(value = "hello.aop.order.aop.Pointcuts.orderAndService()", returning = "result")
public void doReturn(JoinPoint joinPoint, Object result) {
log.info("[return] {} return={}", joinPoint.getSignature(), result);
}
|
cs |
●메서드 실행이 정상적으로 반환될 때 실행
●returning 속성에 사용된 이름은 어드바이스 메서드의 매개변수 이름과 일치해야 함
●returning 절에 지정된 타입의 값을 반환하는 메서드만 대상을 실행
(3)After throwing
-메서드가 예외를 던지는 경우에 실행
-메서드를 실행하는 도중 예외가 발생한 경우 공통 기능을 실행함
1
2
3
4
|
@AfterThrowing(value = "hello.aop.order.aop.Pointcuts.orderAndService()", throwing = "ex")
public void doThrowing(JoinPoint joinPoint, Exception ex) {
log.info("[ex] {} message={}", joinPoint.getSignature(), ex.getMessage());
}
|
cs |
●메서드 실행이 예외를 던져서 종료될 때 실행
●throwing 속성에 사용된 이름은 어드바이스 메서드의 매개변수 이름과 일치해야 함
●throwing 절에 지정된 타입과 맞은 예외를 대상으로 실행
(4)After(Finally)
-조인 포인트의 동작(정상 또는 예외)과는 상관없이 실행
-메서드 실행 후 공통 기능을 실행
-일반적으로 리소스를 해제하는데 사용
(5)Around
-메서드 호출 전후에 수행하며 가장 강력한 어드바이스(조인 포인트 실행 여부 선택, 반환 값 변환, 예외 변환 등이 가능)
-메서드 실행 전 & 후, 예외 발생 시점에 공통 기능을 실행
-어드바이스의 첫 번째 파라미터는 ProceedingJoinPoint를 사용해야 함
-proceed()를 통해 대상을 실행하며, proceed()를 여러번 실행할 수 있음
+@Around만 있어도 모든 기능 수행이 가능함(가장 강력한 어드바이스이며 대부분의 기능을 제공하지만 타겟 등 고려해야할 사항이 있을 때 정상적으로 작동이 되지 않는 경우가 있음)
+좋은 설계는 @Around만 사용해서 모두 해결하는 것보다는 제약을 가지더라도 실수를 미연에 방지하는 것
2-3.Pointcut 표현식
-포인트컷 표현식은 AspectJ pointcut expression ⇒ AspectJ가 제공하는 포인트컷 표현식을 줄여서 표현하는 것
-포인트컷 표현식은 execution 같은 포인트컷 지시자(Pointcut Designator, PCD)로 시작
-(1)포인트컷 지시자 종류
(2)Pointcut 표현식 결합
-포인트컷 표현식은 &&, ||, ! 를 사용하여 결합할 수 있음
-이름으로 pointcut 표현식을 참조 가능
(3)일반적인 Pointcut 표현식들
- 모든 공개 메서드 실행
- execution(public * *(..))
- set 다음 이름으로 시작하는 모든 메서드 실행
- execution(* set*(..))
- AccountService 인터페이스에 의해 정의된 모든 메소드의 실행
- execution(* com.xyz.service.AccountService.*(..))
- service 패키지에 정의된 메서드 실행
- execution(* com.xyz.service.*.*(..))
- 서비스 패키지 또는 해당 하위 패키지 중 하나에 정의된 메서드 실행
- execution(* com.xyz.service..*.*(..))
- 서비스 패키지 내의 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
- within(com.xyz.service.*)
- 서비스 패키지 또는 하위 패키지 중 하나 내의 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
- within(com.xyz.service..*)
- AccountService 프록시가 인터페이스를 구현하는 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
- this(com.xyz.service.AccountService)
- AccountService 대상 객체가 인터페이스를 구현하는 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
- target(com.xyz.service.AccountService)
- 단일 매개변수를 사용하고 런타임에 전달된 인수가 Serializable과 같은 모든 조인 포인트 (Spring AOP에서만 메소드 실행)
- args(java.io.Serializable)
- 대상 객체에 @Transactional 애너테이션이 있는 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
- @target(org.springframework.transaction.annotation.Transactional)
- 실행 메서드에 @Transactional 애너테이션이 있는 조인 포인트 (Spring AOP에서만 메서드 실행)
- @annotation(org.springframework.transaction.annotation.Transactional)
- 단일 매개 변수를 사용하고 전달된 인수의 런타임 유형이 @Classified 애너테이션을 갖는 조인 포인트(Spring AOP에서만 메서드 실행)
- @args(com.xyz.security.Classified)
- tradeService 라는 이름을 가진 스프링 빈의 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
- bean(tradeService)
- 와일드 표현식 *Service 라는 이름을 가진 스프링 빈의 모든 조인 포인트
- bean(*Service)
2-4.JointPoint
-조인 포인트는 추상적인 개념으로, AOP를 적용할 수 있는 지점을 의미
-어드바이스가 적용될 수 있는 위치, 메소드 실행, 생성자 호출, 필드 값 접근, static 메서드 접근 같은 프로그램 실행 중 지점을 나타냄
-AspectJ를 사용해서 컴파일 시점과 클래스 로딩 시점에 적용하는 AOP는 바이트코드를 실제 조작하기 때문에 해당 기능을 모든 지점에 다 적용할 수 있음
-프록시를 사용하는 스프링 AOP의 조인 포인트는 메서드 실행으로 제한됨
-프록시 방식을 사용하는 스프링 AOP는 스프링 컨테이너가 관리할 수 있는 스프링 빈에만 AOP를 적용할 수 있음
(1)JoinPoint 인터페이스의 주요 기능
-JoinPoint.getArgs() : JoinPoint에 전달된 인자를 배열로 반환
-JoinPoint.getThis() : AOP 프록시 객체를 반환
-JoinPoint.getTarget() : AOP가 적용된 대상 객체를 반환
-JoinPoint.getSignature() : 조언되는 메서드에 대한 설명을 반환
*클라이언트가 호출한 메소드의 시그니처(리턴타입, 이름, 매개변수) 정보가 저장된 Signature 객체를 반환
**Signature : 객체가 선언하는 모든 연산은 연산의 이름, 매개변수로 받아들이는 객체들
**Signature가 제공하는 메서드 3가지
***String getName() : 클라이언트가 호출한 메소드의 이름을 반환
***String toLongString() : 클라리언트가 호출한 메소드의 리턴타입, 이름, 매개변수를 패키지 경로까지 포함해서 반환
***String toShortString() : 클라이언트가 호출한 메소드 시그니처를 축약한 문자열로 반환
-JoinPoint.toString() : 조언되는 방법에 대한 유용한 설명을 인쇄
(2)ProceedingJoinPoint 인터페이스의 주요 기능
-proceed() : 다음 어드바이스나 타켓을 호출
2-5.Annotation을 이용한 AOP
-@AspectJ 지원
(1)@AspectJ는 애너테이션이 있는 일반 Java 클래스로 관점을 선언하는 스타일
(2)@AspectJ 지원 활성화 : XML 또는 Java 스타일 설정으로 활성화할 수 있음
*XML 설정 : aop:aspectj-autoproxy 요소를 사용
*Java 설정 : @Configuration으로 @AspectJ 지원을 활성화하려면 @EnableAspectJAutoProxy 애너테이션을 추가
(3)Aspect 선언 : @AspectJ 지원이 활성화되면 @AspectJ 관점(@Aspect 애너테이션이 있음)이 있는 클래스로 애플리케이션 컨텍스트에 정의된 모든 빈이 Spring에서 자동으로 감지되고 Spring AOP를 구성하는 데 사용됨
(4)포인트컷 선언 : 포인트컷은 관심 조인 포인트를 결정하므로 어드바이스가 실행되는 시기를 제어할 수 있음
*pointcut 선언은 이름과 매개변수를 포함하는 서명과 우리가 관심 있는 메소드 실행을 정확히 결정하는 pointcut 표현식의 두 부분으로 구성됨
*pointcut 표현식은 @Pointcut 어노테이션을 사용하여 표시
(5)어드바이스 선언 : 어드바이스는 포인트컷 표현식과 연관되며 포인트컷과 일치하는 메서드 실행 전후 또는 전후에 실행됨
*pointcut 표현식은 명명된 pointcut에 대한 단순 참조이거나 제자리에 선언된 pointcut 표현식일 수 있음
-이미지 및 내용 출처 : code states
'부트캠프' 카테고리의 다른 글
Spring MVC - API 계층 part 2 (0) | 2023.02.14 |
---|---|
Spring MVC - API계층 part 1 (0) | 2023.02.13 |
Spring Framework 핵심 개념 - DI (0) | 2023.02.07 |
Spring Framework 기본 (1) | 2023.02.03 |
Spring Framework 소개 (1) | 2023.02.02 |