AOP(Aspect Oriented Programming)

ImOk·2021년 12월 29일
0

👩‍💻 웹 개발

목록 보기
12/14
post-thumbnail

AOP(Aspect Oriented Programming)

AOP는 OOP를 보완하는 수단으로, 흩어진 Aspect 를 모듈화 할 수 있는 프로그래밍 기법이다.
기존의 OOP 언어에서는 횡단 관심에 해당하는 공동 코드를 완벽하게 독립적인 모듈로 분리해 내기 어려웠다.
AOP는 핵심 기능과 공통 기능의 구현을 분리함으로써, 핵심 기능을 구현한 코드의 수정 없이 공통 기능을 적용할 수 있게 만들어준다.
핵심 기능의 코드를 수정하지 않으면서 공통 기능의 구현을 추가하는 것이 AOP


1. AOP 주요 용어

AOP 용어설명
횡단 관심(Crosscutting Concerns) 비지니스 메소드마다 공통으로 등장하는 코드를 의미(예외, 로깅, 트랜잭션같은 코드)
핵심 관심(Core Concerns)사용자의 요청에 따라 실제 수행되는 핵심 비지니스 로직을 의미.
Aspect구현하고자하는 횡단 관심사의 기능, 여러 곳에 쓰이는 코드를 모듈화. Pointcut과 Advice의 결합
Advice횡단관심에 해당하는 코드를 담고 있다. 실질적으로 어떤 일을 해야하는지를 담고 있다.
TargetAspect에 적용되는 곳, Advice를 받는 클래스
JoinpointAdvice가 Target에 적용되는 시점. 메서드 진입 시점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용가능
Pointcut어디에 적용해야 하는지에 대한 정보를 담고 있다. Joinpoint의 상세 스펙 정의
WeavingAdvice를 핵심기능에 적용하는 행위

1-1.Pointcut 표현식

포인트컷 표현식은 메소드처럼 생긴 execution 명시자를 이용하며, execution 명시자 안에 포인트컷 표현식을 기술한다.

1-1-1. 리턴타입 지정

표현식설명
*모든 리턴타입
void리턴타입이 void
!void리턴타입이 void 아님

1-1-2. 패키지 지정

표현식설명
com.enc.biz정확한 com.enc.biz 패키지만 선택
com.enc.biz..com.enc.biz 패키지로 시작하는 모든 패키지
com.enc.biz..implcom.enc.biz 패키지로 시작하고 마지막 패키지 이름이 impl로 끝나는 패키지

1-1-3. 클래스 지정

표현식설명
BoardServiceImpl정확하게 BoardServiceImpl 클래스만 선택
*Impl클래스 이름이 Impl로 끝나는 클래스만 선택
BoardService+클래스 이름 뒤에 '+' 가 붙으면 클래스로부터 파생된 모든 자식 클래스 선택

1-1-4. 메소드 지정

표현식설명
*(..)가장 기본 설정으로 모든 메소드 선택
get*(..)메소드 이름이 get으로 시작하는 모든 메소드 선택

1-1-5. 매개변수 지정

표현식설명
(..)가장 기본 설정
(*)반드시 1개의 매개변수를 가지는 메소드 선택
(com.enc.biz.user.UserVO)매개변수로 UserVO를 가지는 메소드만 선택
(!com.enc.biz.user.UserVO)매개변수로 UserVO를 가지지 않는 메소드만 선택
(Integer, ..)한 개 이상의 매개변수를 가지되, 첫 번째 매개변수의 타입이 Integer인 메소드만 선택
(Integer, *)반드시 두 개의 매개변수를 가지되, 첫 번째 매개변수의 타입이 Integer인 메소드만 선택

2. Spring에서 AOP 구현 방식

2-1. XML(schema) 기반의 AOP구현

  • aspectjweaver 의존설정(pom.xml)
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.6</version>
</dependency>
  • xml 스키마 설정

  • xml에 AOP 설정
	<bean id="log" class="com.enc.biz.common.LogUserAdvice"></bean>
	
	<aop:config>
		<aop:pointcut id="allPointcut" expression="execution(* com.enc.biz..*Impl.*(..))" />
		<aop:aspect ref="log">
		<!-- XML(before) -->
			<aop:before pointcut-ref="allPointcut" method="printLogTest1" />
		<!-- XML(after) -->
			<aop:after pointcut-ref="allPointcut" method="printLogTest2" />
		<!-- XML(around) -->	
			<aop:around pointcut-ref="allPointcut" method="printLogTest3" />
		</aop:aspect>  
	</aop:config> 

2-2. Annotation 기반의 AOP구현

  • @Aspect 어노테이션을 이용해서 공통으로 적용할 기능을 구현한 경우, XML 설정에서 이를 인식할 수 있도록 <aop:aspectj-autoproxy /> 태그를 추가 한다.
<bean id="log4j" class="com.enc.biz.common.Log4jUserAdvice"></bean>
<aop:aspectj-autoproxy />
  • 클래스에 @Aspect 어노테이션 적용
  • @Pointcut 어노테이션을 적용하여 PointCut 설정
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class Log4jUserAdvice {
	
	@Pointcut("execution(* com.enc.biz..*Impl.get*(..))")
	public void pointcutTarget() {}
	
	@Before("pointcutTarget()")
	public void printLoggingTest1() {
		System.out.println("[@Before log - Log4j] User Buiness Logic 수행");
	}
	
	@After("pointcutTarget()")
	public void printLoggingTest2() {
		System.out.println("[@After log - Log4j] User Buiness Logic 수행");
	}

3. AOP 태그의 종류

태그설명
<aop:before>비즈니스 메소드 실행 전에 Advice 메소드 실행
<aop:after-returning>비즈니스 메소드가 정상적으로 실행 후 적용되는 Advice를 정의
<aop:after-throwing>비즈니스 메소드가 예외를 발생시킬 때 적용되는 Advice를 정의 (catch같은 역할)
<aop:after>예외 발생 여부 상관없이 적용되는 Advice를 정의 (finally같은 역할)
<aop:around>비즈니스 메서드 호출 이전, 이후, 예외 발생 등 모든 시점에 적용 가능한 Advice를 정의

3-1 around의 proceed() 메소드

around 의 Advice는 클라이언트 호출을 가로챈다. 비즈니즈 메소드에 대한 정보를 Spring 컨테이너가 around Advice 메소드로 넘겨주는데, 그게 ProceedingJoinPoint 객체이다.

비지니스 메소드로 진행하도록(proceed) 하는 메소드가 proceed() 메소드이다.
proceed()를 기준으로 비즈니스 메소드 수행 전과 후가 나뉜다.
Object result = joinPoint.proceed(); : proceed()메소드 반환 값인 Object에는 비즈니스 메소드가 실행한 후의 결과 값들이 담겨 있다. (ex) UserVo)

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class Log4jUserAdvice {
	
	@Pointcut("execution(* com.enc.biz..*Impl.get*(..))")
	public void pointcutTarget() {}
	
	@Around("pointcutTarget()")
	public void printLoggingTest(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("[@Around log start - Log4j] User Buiness Logic 수행");
		Object result = joinPoint.proceed();
		System.out.println("===> result:: " + result);
		System.out.println("[@Around log end - Log4j] User Buiness Logic 수행");
	}
}

🔗 참고자료

https://ktko.tistory.com/entry/Spring-AOP-%EA%B0%9C%EB%85%90-%EC%84%A4%EB%AA%85?category=703665

profile
ImOk👌

0개의 댓글