본문 바로가기

Archived(Programming)/Spring #2(기초)

AOP(Aspect Oriented Programming)

# AOP

  • 업무 로직을 포함하는 기능을 핵심기능(Core conecrens)
  • 핵심기능을 도와주는 부가적인 기능(로깅, 보안 등)을 부가 기능(Cross-cutting Concerns)이라고 부른다.
  • 객체 지향의 기본 원칙을 적용하여도 핵심기능에서 부가기능을 분리해서 모듈화하는 것은 매우 어렵다.
  • 핵심기능과 부가기능을 별도로 관리하여 런타임 시에 처리할 수 있도록 지원하는 것이 AOP

AOP는 애플리케이션에서 관심사의 분리(기능의 분리)

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

# Aspect(Aspect = Advice + PointCut)

  • 애스펙트는 부가기능을 정의한 코드인 Advice와 이를 어디에 적용할지를 결정하는 PointCut을 합친 개념
  • AOP 개념을 적용하면 핵심기능 코드 사이에 침투된 부가기능을 독립적인 애스펙트로 구분해낼 수 있음
  • 구분된 부가기능 애스펙트를 런타임 시에 필요한 위치에 동적으로 참여하게 할 수 있음

# AOP 용어

  • Target: 핵심 기능을 담고 있는 모듈로, 타깃은 부가기능을 부여할 대상이 됨
  • Advice: 부가기능을 담고 있는 모듈
  • Join Point: Advice가 적용될 위치, 타깃 객체가 구현한 인터페이스의 모든 메서드는 조인 포인트가 됨
  • PointCut: Advice를 적용할 타깃의 메서드를 선별하는 정규표현식(execution으로 시작하고 메서드의 Signature를 비교하는 방법을 주로 이용)
  • Aspect: AOP의 기본모듈, Advice + PointCut, 싱글톤 형태의 객체로 존재
  • Adviser: 어드바이저는 Aspect와 동일 용어(Spring AOP에서 사용되는 특별한 용어)
  • Weaving: 위빙은 포인터컷에 의해서 결정된 타깃의 조인 포인트에 부가기능을 삽입하는 과정(핵심적인 처리과정)

AOP

# Spring AOP 특징

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

  • Spring은 타깃 객체에 대한 프록시를 만들어 제공
  • 타깃을 감싸는 프록시는 실행시간에 생성됨
  • 프록시는 어드바이스를 타깃 객체에 적용하면서 생성되는 객체임

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

  • 프록시는 타긱 객체에 대한 호출을 가로챈 다음 어드바이스의 부가기능 로직을 수행하고 난 후에 타깃의 핵심기능 로직을 호출함(전처리 어드바이스)
  • 타깃의 핵심기능 로직 메서드를 호출한 후에 부가기능(어드바이스)을 수행하는 경우도 있음(후처리 어드바이스)

3) Spring AOP는 메서드 조인 포인트만 지원

  • Spring은 동적 프록시를 기반으로 AOP를 구현하므로 메서드 조인 포인트만 지원함
  • 즉, 핵심기능(타깃)의 메서드가 호출되는 런타임 시점에만 부가기능(어드바이스)을 적용할 수 있음
  • 반면에 AspectJ 같은 고급 AOP 프레임워크를 사용하면 객체의 생성, 필드값의 조회와 조작, static 메서드 호출 및 초기화 등의 다양한 작업에 부가기능을 적용할 수 있음

# 실습 

의존성 설치(spring-aop, aspectj weaver)

AOP 자동 프록시 설정(root-context.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
	
	<aop:aspectj-autoproxy/>
	
	<context:component-scan base-package="kr.co.acomp.hello">
		<context:exclude-filter type="annotation"
			expression="org.springframework.stereotype.Controller"/>
	</context:component-scan>
	
</beans>

SampleAspect 생성

package kr.co.acomp.hello.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class SampleAspect {
	
	@Before("execution(* kr.co.acomp.hello..*.*(..))")
	public void before(JoinPoint joinPoint) {
		String targetMethodName =
				joinPoint.getSignature().getName();
		
		System.out.println(targetMethodName + "is invoked..");
	}
}

Aspect 적용 확인

'Archived(Programming) > Spring #2(기초)' 카테고리의 다른 글

트랜잭션과 로깅  (0) 2020.03.18
PointCut 표현식과 Advisor 구현  (0) 2020.03.17
Dynamic SQL  (0) 2020.03.17
Mapper XML 파일  (1) 2020.03.16
Spring Mybatis  (0) 2020.03.15