금융에 대한 모든 것

스프링 AOP란?

 웹 애플리케이션을 개발할 때 주요 기능이지는 않지만 공통적으로 꼭 동작해야 하는 기능이 있는데, 트랜잭션이나 예외처리, 로깅 등이 이에 해당합니다. AOP란 이런 공통 기능을 중복하지 않고 최대한 재사용하기 위해 만들어진 프로그래밍 기법입니다. AOP 기능을 이용하면 메서드 안의 주요 기능과 공통 기능을 분리해 선택적으로 공통 기능을 메서드에 적용할 수 있기 때문에 유지보수가 편리한 장점이 있습니다.

 

스프링 AOP 용어

 AOP에서는 객체, 시점 등을 정의하는 몇 가지 용어가 존재합니다.

용어

의미

Advice

공통 기능을 적용할 시점을 지정합니다. 

Jointpoint

Advice를 적용 가능한 지점을 의미합니다.

Pointcut

실제 Advice가 적용되는 Jointpoint를 나타냅니다.

Weaving 

Advice를 핵심적인 로직 코드에 적용하는 것을 weaving이라고 합니다.

Aspect

여러 객체에 공통으로 적용될 기능을 나타냅니다.

proxy

Advice가 적용되었을 때 만들어지는 객체입니다.

 

Advice의 종류

종류

설명

Before

대상 객체의 메서드가 호출되기 전에 기능을 실행합니다

After Advice

대상 객체의 메서드가 호출된 후에 기능을 실행합니다.

Around Advice

대상 객체의 메서드가 호출되기 전, 후에 모두 기능을 실행합니다.

 

AOP 기능 설정

 먼저 pom.xml 파일에 아래와 같이 aop 라이브러리 denpendency를 추가합니다.

pom.xml

<!-- 스프링 프로젝트에 설정되어 있음-->
    <properties>
                <java-version>1.8</java-version>
                <org.springframework-version>5.1.4.RELEASE</org.springframework-version>
                <org.aspectj-version>1.9.2</org.aspectj-version>
                <org.slf4j-version>1.7.25</org.slf4j-version>
        </properties>
    
<!-- AspectJ -->
        <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>${org.aspectj-version}</version>
        </dependency>

 그다음 servlet-context.xml 파일로 들어가서 namespace탭을 누른 후 aop 체크박스에 체크합니다. 이렇게 하면 servlet-context에 aop 태그를 사용할 수 있게 됩니다.

 

그런 다음 servlet-context.xml 파일에 위와 같이 aop태그를 입력하여 aop 어노테이션을 사용할 수 있도록 합니다. 이렇게 하면 aop 기능을 사용할 수 있게 됩니다.

 

servlet-context.xml

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

 

AOP 기능 사용하기

예시

@Aspect
@Component
public class A {}

먼저 공통 기능으로 사용될 클래스를 만들어 @Aspect 어노테이션을 지정합니다. 그리고 @Aspect가 붙은 클래스를 빈으로 등록해야 되기 때문에 @Component를 추가적으로 붙여줍니다.

 

@Aspect
@Component
public class A {
         
    @Around("execution(* package.class.method(..))")
    public Object measure(ProceedingJoinPoint joinPoint) throws Throwable {
    
    }
}

 jointPoint를 인자로 받는 메서드를 만들어서 @Around를 지정합니다. 그리고 @Around의 속성 값으로 execution 명시자를 이용해 공통 기능이 적용될 메서드들을 명시하고 있는 모습입니다.

 

public Object measure(ProceedingJoinPoint jointPoint) throws Throwable {
   // 메서드가 호출되기 전에 먼저 실행되는 코드
   long start = System.currentTimeMillis();
   // 메서드가 호출되는 시점
   Object result = jointPoint.proceed();
    // 메서드가 호출된 실행되는 코드
   long end = System.currentTimeMillis();
   System.out.println(end-start);
   return result;
   }

jointpoint, 즉, 메서드가 호출되는 시점의 전과 후에 실행될 코드를 작성합니다.

 

결과

52000ns

 package 패키지에 있는 class 클래스에 속한 method라는 메서드가 실행될 때마다 메서드의 실행시간이 출력됩니다.

 

execution 명시자

 execution 명시자를 이용하여 공통 기능이 적용될 메서드를 지정할 수 있습니다.

사용법

execution("수식어 리턴타입 클래스명 메서드명(파라미터)")

명시자 표현식을 위와 같은 순서로 형식으로 입력합니다. '*'은 나타낼 수 있는 모든 값을 나타내고 '..' 하나 이상의 값을 나타냅니다.

 

예시

execution("public void method*(..)")

메서드명이 method로 시작하고 파라미터가 하나 이상인 메서드를 지정하고 있는 표현식입니다.

 

execution("* package.*.*()")

이름이 package인 패키지에 있는 모든 클래스에 속하고, 파라미터가 없는 모든 메서드를 지정하고 있는 표현식입니다.

 

execution("* package..*.method(*, *)")

 이름이 package인 패키지 및 하위 패키지에 있는 모든 클래스에 속하고, 파라미터 2개를 받는 메서드를 지정하고 있는 표현식입니다.

반응형