스프링 AOP(Aspect Oriented Programming)
AOP(Aspect Oriented Programming)는 로깅과 같은 기본적인 기능에서부터 트랜잭션이나 보안과 같은 기능에 이르기까지 어플리케이션 전반에 걸쳐 적용되는 공통기능을 핵심 기능과 분리해서 모듈로 구현한 뒤 핵심 기능이 수행될 때 필요로 하는 곳에 공통기능이 적용되게 하는 기능이다. 공통의 관심사항을 적용해서 발생하는 의존 관계의 복잡성과 코드 중복을 해소해 주는 프로그래밍 기법이다.
하나의 파일에
1. 내용들을 콘솔에 기능 출력 =>공통기능(로그처리, 보안, 트랜잭션처리)
2. 핵심기능(고유기능)이 동작
3. 로그 출력 => 공통기능
공통기능이 변경될 경우 파일을 다 열어서 수정해야하므로 유지 보수 기능이 떨어진다.
그래서 AOP가 나왔다. (관점지향프로그래밍)
일반프로그램에는 AOP가 적용되어있지않다.
공통기능을 별도로 뽑아내고, 핵심기능만 있는 파일을 만들어낸다. (공통기능과 핵심기능을 분리)
공통기능을 원하는 시점에 결합시킨다
( 공통기능(로그처리, 보안, 트랜잭션처리)을 핵심기능 전에 적용할 것인지, 후에 적용할 것인지)
AOP기능을 이용해서 핵심기능을 검색할 수도 있다.
핵심기능이 반환타입을 항상 갖는게아니라 void형 일 수도 있다.
Aop 사용할때는 라이브러리 추가해야 에러안난다.
Pom.xml에 추가한다.
- AOP 용어
Advice | 언제 공통 관심 기능을 핵심 로직에 적용할 지를 정의. |
Joinpoint | Advice를 적용 가능한 지점을 의미. 메서드 호출, 필드 값 변경 등이 Joinpoint에 해당 |
Pointcut | Joinpoint의 부분 집합으로서 실제로 Advice가 적용되는 Joinpoint를 나타냄. |
Weaving | Advice를 핵심 로직 코드에 적용하는 것을 weaving이라고 함. |
Aspect | 여러 객체에 공통으로 적용되는 공통 관심 사항 |
- 세 가지 Weaving 방식
- 컴파일 시점에 코드에 공통 기능을 추가하는 방법 (스프링 기본 지원이 아니며 AspectJ와 같이 AOP를 위한 전용 도구를 사용해야 함)
- 클래스 로딩 시점에 바이트 코드에 공통 기능을 추가하는 방법 (스프링 기본 지원이 아니며 AspectJ와 같이 AOP를 위한 전용 도구를 사용해야 함)
- 런타임에 프록시 객체를 생성해서 공통 기능을 추가하는 방법 (스프링이 제공하는 AOP 방식)
- 스프링에서의 AOP
- XML 스키마 기반의 POJO 클래스를 이용한 AOP 구현
- @Aspect 어노테이션 기반의 AOP 구현
- 구현 가능한 Advice 종류
종류 | 설명 |
Before Advice | 대상 객체의 메서드(핵심기능) 호출 전에 공통기능을 실행 |
After Returning Advice | 대상 객체의 메서드가 예외 없이 실행한 이후에 공통 기능을 실행 |
After Throwing Advice | 대상 객체의 메서드를 실행하는 도중 예외가 발생한 경우에 공통 기능을 실행 (예외가 발생했을 경우에만 등장) |
After Advice | 대상 객체의 메서드를 실행하는 도중에 예외가 발생했는지의 여부와 상관없이 메서드 실행 후 공통 기능을 실행. (try~catch~finally의 finally블럭과 비슷) |
Around Advice | 대상 객체의 메서드 실행 전, 후 또는 예외 발생 시점에 공통 기능을 실행하는데 사용 |
XML 스키마를 이용한 AOP 설정
AspectJ의 Pointcut 표현식 (핵심기능을 검색하는 방법)
<aop:aspect id="traceAspect1" ref="performanceTraceAdvice"> <aop:pointcut expression="execution(public * com.spring.board..*(..))" id="publicMethod"/> <aop:around method="trace" pointcut-ref="publicMethod"/> </aop:aspect> |
execution 명시자는 Advice를 적용할 메서드를 명시할 때 사용됨
execution(식어패턴 리턴타입패턴 클래스이름패턴 이름패턴(파라미터패턴) |
예)
- execution(public void set*(..)) 리턴 타입이 void이고 메서드 이름이 set으로 시작하고, 파라미터가 0개 이상인 메서드 호출 |
- execution(* com.spring.ch01.*.*()) //패키지.클래스.메서드 com.spring.ch01 패키지의 파라미터가 없는 모든(*) 메서드 호출 |
- execution(* com.spring.ch01..*.*(..)) //..하위패키지까지 확장 com.spring.ch01 패키지 및 하위 패키지에 있는 파라미터가 0개 이상인 메서드 호출 |
- execution(Integer com.spring.ch01..WriteArticleService.write(..)) 리턴 타입이 Integer인 kr.spring.ch01 패키지 및 하위 패키지의 WriteArticleService 인터페이스의 write() 메서드 호출 |
- execution(* get*(*)) 이름이 get으로 시작하고 1개의 파라미터를 갖는 메서드 호출 |
- execution(* get*(*,*)) 이름이 get으로 시작하고 2개의 파라미터를 갖는 메서드 호출 |
- execution(* read*(Integer,*)) 메서드 이름이 read로 시작하고, 첫 번째 파라미터 타입이 Integer이며, 1개 이상의 파라미터를 갖는 메서드 호출 |
<!-- Aspect 설정 : Advice를 어떤 Pointcut에 적용할지 설정 --> <aop:config> <aop:aspect id="traceAspect1" ref="performanceTraceAdvice"> <aop:pointcut expression="execution(public * com.spring.board..*(..))" id="publicMethod"/> <aop:around method="trace" pointcut-ref="publicMethod"/> </aop:aspect> </aop:config> <bean id="writeArticleService" class="com.spring.board.service.WriteArticleServiceImpl"> <constructor-arg> <ref bean="articleDao"/> </constructor-arg> </bean> <bean id="articleDao" class="com.spring.board.dao.WriteArticleDao"/> |
Advice 정의 관련 태그
종류 | 설명 |
<aop:before> | 메서드 실행 전에 적용되는 Advice를 정의한다. |
<aop:after-returning> | 메서드 정상적으로 실행된 후에 적용되는 Advice를 정의한다. |
<aop:after-throwing> | 메서드가 예외를 발생시킬 때 적용되는 Advice를 정의한다. try-catch블록에서 catch 블록과 비슷하다. |
<aop:after> | 메서드가 적상적으로 실행되느니지 또는 예외를 발생시키는지 여부에 상관없이 적용되는 Advice를 정의한다. try-catch-finally에서 finally 블록과 비슷하다. |
<aop:around> | 메서드 호출 이전, 이후, 예외 발생 등 모든 시점에 적용 가능한 Advice를 정의한다. Around Advice를 설정함 |
<aop:config> | AOP 설정 정보임을 나타냄 |
<aop:aspect> | Aspect를 설정함 |
<aop:pointcut> | Pointcut을 설정함 |
@Aspect 어노테이션을 이용한 AOP
<!-- 어노테이션 방식으로 AOP를 구현할 경우 명시해야할 것 -->
<aop:aspectj-autoproxy/>
@Aspect
public class ProfilingAspect {
@Pointcut("execution(public * com.spring.board..*(..))")
private void profileTarget(){}
@Around("profileTarget()")
public Object trace(ProceedingJoinPoint joinPoint)
throws Throwable{
종류 | 설명 |
Before Advice @Before |
대상 객체의 메서드(핵심기능) 호출 전에 공통기능을 실행 |
After Returning Advice @AfterReturning |
대상 객체의 메서드가 예외 없이 실행한 이후에 공통 기능을 실행 |
After Throwing Advice @AfterThrowing |
대상 객체의 메서드를 실행하는 도중 예외가 발생한 경우에 공통 기능을 실행 (예외가 발생했을 경우에만 등장) |
After Advice @After |
대상 객체의 메서드를 실행하는 도중에 예외가 발생했는지의 여부와 상관없이 메서드 실행 후 공통 기능을 실행. (try~catch~finally의 finally블럭과 비슷) |
Around Advice @Around |
대상 객체의 메서드 실행 전, 후 또는 예외 발생 시점에 공통 기능을 실행하는데 사용 |
'WEB > ✿Spring Framework' 카테고리의 다른 글
[Spring] 🔗6) 로깅처리 (0) | 2022.03.05 |
---|---|
[Spring] 🔗4) Spring MVC (0) | 2022.02.25 |
[Spring] 🔗1) IoC컨테이너(Spring 컨테이너) (0) | 2022.02.24 |
[Spring] 🔗Spring Framework (0) | 2022.02.24 |
[Spring] 🔗basic (0) | 2022.02.22 |
댓글