나의개발일지

Spring) AOP 본문

Back-End/Spring

Spring) AOP

아. 이렇게 하면 될거 같은데.. 2024. 4. 17. 23:52
728x90



AOP ( Aspect Oriented Programming )

등장 배경

  • 핵심 관심 사항(core concern)과 공통(부가) 관심 사항 (cross-cutting concern)
    • 기존 OOP에서는 공통관심사항을 여러 모듈에서 적용하는데 있어 중복된 코드를 양상 하는 한계가 존재함
    • 이를 해결하기 위해 AOP가 등장
    • Aspect Oriented Programming은 문제를 해결하기 위한 핵심 관심 사항과 전체에 적용되는 공통 관심 사항을 기준으로 프로그래밍함으로써 공통 모듈을 손쉽게 적용할 수 있게 함

 

OOP란?

 

객체지향

객체 : 주체가 아닌 것, 주체가 활용하는 것 객체 지향 프로그래밍 : 주변의 많은 것들을 객체화 해서 프로그래밍 하는것 객체 지향 언어의 특징 OOP is A P.I.E Abstraction(추상화) Polymorphism(다형성) Inh

cacaodotori.tistory.com

 

개요

  • AOP는 application에서의 관심사의 분리(기능의 분리) 즉, 핵심적인 기능에서 부가적인 기능을 분리한다
  • 분리한 부가기능 어스펙트(Aspect)라는 독특한 모듈 형태로 만들어서 설계하고 개발하는 방법
  • OOP를 적용하여도 핵심기능에서 부가기능을 쉽게 분리된 모듈로 작성하기 어려운 문제점을 AOP가 해결
  • AOP는 부가기능을 어스펙트(Aspect)로 정의하여, 핵심기능에서 부가기능을 분리함으로써 핵심기능을 설계하고 구현할 때 객체지향적인 가치를 지킬 수 있도록 도화주는 개념

 

 

 

그림과 같이 기존 Application 에서는 핵심 관심사항과 공통 관심사항이 한 곳에 몰려있지만 AOP를 적용한 Application은핵심 관심사항과 공통 관심사항이 분리되어 효율적인 유지보수를 할 수 있게 되고 객체 지향적인 가치를 얻게 된다.


Spring AOP

AOP 용어

용어 설명
Target 핵심기능을 담고 있는 모듈로 target은 부가기능을 부여할 대상이 됨.
Advice 어느 시점(Ex : method의 수행 전/후, 예외 발생 후 등..)에 어떤 공통 관심 기능(Aspect)을 적용할지 정의 한 것.
Target에 제공할 부가기능을 담고 있는 모듈.
JoinPoint Aspect가 적용 될 수 있는 지점. (method, field)
즉, target 객체가 구현한 인터페이스의 모든 method는 JoinPoint가 됨.
Pointcut 공통 관심 사항이 적용될 JoinPoint
Advice를 적용할 target의 method를 선별하는 정규 표현식.
Pointcut 표현식은 execution으로 시작하고 method의 Signature를 비교하는 방법을 주로 이용
Aspect 여러 객체에서 공통으로 적용되는 공통 관심 사항. (transaction, logging, security..)
AOP의 기본 모듈.
Aspect = Advice + Pointcut
Aspect는 Singleton 형태의 객체로 존재
Advisor Advisor = Advice + pointcut
Advisor는 Spring AOP에서만 사용되는 특별한 용어
Weaving 어떤 Advice를 어떤 Pointcut(핵심사항)에 적용시킬 것인지에 대한 설정(Advisor)
즉 Pointcut에 의해서 결정된 타겟의 JoinPoint에 부가기능(Advice)을 삽입하는 과정을 뜻함
Weaving은 AOP의 핵심기능(Target)의 코드에 영향을 주지 않으면서 필요한 부가기능(Advice)을 추가할 수 있도록 해주는 핵심적인 처리과정

 

Spring AOP 특징

Spring은 프록시(Proxy) 기반 AOP를 지원

  • Spring은 Target 객체에 대한 Proxy를 만들어 제공
  • Target을 감싸는 Proxy는 실행시간(Runtime)에 생성
  • Proxy는 Advice를 Target 객체에 적용하면서 생성되는 객체

프록시(Proxy)가 호출을 가로챈다 (Intercept)

  • Proxy는 Target 객체에 대한 호출을 가로챈 다음 Advice의 부가기능 로직을 수행하고 난 후에 Target의 핵심 기능 로직을 호출한다. (전처리 Advice)
  • 또는 Target의 핵심 기능 로직 method를 호출한 후에 부가기능(Advice)을 수행하는 경우도 있다 (후처리 Advice)

Spring AOP는 method JoinPoint만 지원

  • Spring은 동적 Proxy를 기반으로 AOP를 구현하므로 method JoinPoint만 지원한다.
  • 즉, 핵심기능 (Target)의 method가 호출되는 런타임 시점에만 부가기능(Advice)를 적용할 수 있다.
  • 반면 AspectJ 같은 고급 AOP framework를 사용하면 객체의 생성, 필드값의 조회와 조작, static method 호출 및 초기화 등의 다양한 작업에 부가기능을 적용할 수 있다.

 

자주쓰는 Point-Cut 표현식

Point-Cut 선택된 Joinpoint
execution(public * * (..)) public 메소드 실행
execution(* set*(..)) 이름이 set으로 시작하는 모든 메소드 실행
execution(* com.test.service.AccountService.*(..)) AccountService 인터페이스의 모든 메소드 실행
execution(* com.test.service.*.*(..)) service 패키지의 모든 메소드 실행
execution(*.com.test.service..*.*(..)) service 패키지와 하위 패키지의 모든 메소드 실행
within(com.test.service.*) service 패키지 내의 모든 결합점
within(com.test.service..*) service 패키지 및 하위 패키지의 모든 결합점

AOP 구현

 

1. POJO Class를 이용한 AOP 구현

XML Schema를 이용한 AOP 설정

 

< aop namespace와 XML Schema 추가 >

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop.xsd">

 

aop namespace를 이용한 설정

<!-- AOP 설정 -->
	<bean id="ptAdvice"
		class="com.ssafy.aop.step01.around.PerformanceTraceAdvice" />

	<!-- com.ssafy.board package안에 있는 Dao로 끝나는 모든 클래스의 모든 메소드에 적용 -->
	<aop:config>
		<aop:aspect id="traceAspect" ref="ptAdvice">
			<aop:pointcut id="publicMethod"
				expression="execution(public * com.ssafy.board..*Dao.*(..))" />
			<aop:around method="trace" pointcut-ref="publicMethod" />
		</aop:aspect>
	</aop:config>

 

 

aop 설정 태그

aop:config aop설정의 root 태그 (weaving들의 묶음.)
aop:aspect Aspect 설정 (하나의 weaving에 대한 설정.)
aop:pointcut Pointcut 설정

 

Advice 설정 태그

aop:before method 실행 전 실행 될 Advice
aop:after-returning method가 정상 실행 후 실행 될 Advice
aop:after-throwing method에서 예외 발생시 실행 될 Advice. (catch block)
aop:after method가 정상 또는 예외 발생에 상관없이 실행 될 Advice (finally block)
aop:around 모든 시점(실행 전, 후) 에서 적용시킬 수 있는 Advice

 

설정파일 aop:aspect

  • 한 개의 Aspect(공동 관심 기능)을 설정
  • ref 속성을 통해 공통 기능을 가지고 있는 bean을 연결
  • id는 이 태그의 식별자 설정
  • 자식 태그로 aop:pointcut advice관련 태그가 올 수 있다.

 

설정 파일 aop:pointcut

  • Pointcut(공통 기능이 적용될 곳)을 지정하는 태그
  • aop:configaop:aspect의 자식 태그
  • AspectJ 표현식을 통해 pointcut 지정
  • 속성
    • id : 식별자로 advice 태그에서 사용됨
    • expression : pointcut 지정

 

POJO 기반 Advice Class 작성

POJO 기반 Aspect Class 작성

  • 설정 파일의 advice 관련 태그에 맞게 작성한다.
  • <bean>으로 등록 하며 aop:aspect의 ref 속성으로 참조한다.
  • 공통 기능 메소드 : advice 관련 태그들의 method 속성의 값이 method의 이름이 된다.

Advice 정의 관련 태그

  • pointcut : 직접 pointcut을 설정, 호출 할 method의 패전 지정
  • pointcut-ref : aop:pointcut 태그의 id명을 넣어 pointcout 지정
  • method : Aspect bean에서 호출할 method명 지정

POJO 기반의 Class로 작성

  • class명이나 method명에 대한 제한은 없다.
  • method 구문은 호출되는 시점에 따라 달라 질 수 있다.
  • method의 이름은 advice 태그 (aop:before) 에서 method 속성의 값이 method명이 된다.

 

2. Annotation을 이용한 AOP 구현

@aspect Annotation을 이용한 AOP 구현

  • @Aspect Annotation을 이용하여 Aspect Class에 직접 Advice 및 Pointcut등을 설정
  • 설정 파일에 <aop:aspectj-autoproxy/>를 반드시 추가
  • Aspect Class를 <bean>으로 등록
  • 어노테이션
  • @Aspect, @Beform, @AffterReturning, @AfterThrowing, @After, @Around
  • Around를 제외한 나머지 method들은 첫 argument로 JoinPoint를 가질 수 있다.
  • Around method는 argument로 ProceedingJoinPoint를 가질 수 있다.
@Aspect
public class PerformanceTraceAdvice {

   @Pointcut("execution(public * com.company.board..*Dao.*(..))")
    public boid profileTarget() {
    }
    
    @Around("profileTarget()")
    public Object trace(ProceedingJoinPoint joinPoint) throw Throwable {
    	String signature = joinPoint.getSignature().toShortString();
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        Object result = joinPoint.proceed();
        
        stopWatch.stop();
        System.out.println(signature + " 실행시간 : " + stopWatch.getTotalTimeMillis());
        
        return result;
        }
    }

 

728x90
반응형

'Back-End > Spring' 카테고리의 다른 글

Spring) Mybatis  (2) 2024.04.23
Spring) Interceptor  (0) 2024.04.19
Spring) DI 의존성 주입  (0) 2024.04.15
Spring) IoC & Container  (0) 2024.04.15
Spring) SpringMVC  (1) 2024.01.04