Spring AOP

JungHwan Oh·2022년 8월 2일
0

1. AOP?

AOP(Aspect oriented Programming) 는 OOP를 보완하는 수단으로, 흩어진 Aspect를 모듈화 할 수 있는 프로그래밍 기법입니다.

[흩어진 관심사]

[AOP 적용]

위 그림을 통해서 관심사들이 흩어져 있는 것을 볼 수 있습니다. 우리는 AOP를 이용해 이렇게 흩어진 관심사들을 Aspect로 모듈화 하고 핵심적인 비니지스 로직에서 분리 재활용 할 수 있습니다. 이것이 AOP의 취지 입니다.

2. AOP 주요 개념

Adivce : 해야 할 일들

Target : 적용이 되는 대상(위 그림으로 본다면 Class A, Class B, Class C 가 해당이 된다)

Join Point : Advice가 적용될 위치 예를 들면 메소드 진입 지점, 생성자 호출 시점, 필드에 서 값을 꺼내올 때 등 다양한 시점에 적용이 가능하다.

PointCut : 필터링 된 조인포인트로 특정 메소드만 혹은 특정 클래스에서만 등등 공통기능을 수행시키기 위해서 사용

3. Proxy-based AOP

Spring AOP 의 핵심 아키텍처는 Proxy 기반입니다.

프록시는 타켓을 감싸서 요청을 대신 받아주는 랩핑 오브젝트 입니다. Client 가 타켓 메소드를 호출 하면 타켓이 아닌 감싸고 있는 프록시가 호출되어 타켓 메소드 실행전에 선처리, 타켓 메소드 실행 후, 후처리를 실행시키도록 구성되어있습니다.

스프링은 내부적으로 JDK Dynamic Proxy 와 CGLIB Proxy 두 가지의 프록시를 구현체로 갖고 있습니다. 똑똑한 스프링은 적용할 대상 객체가 특정 인터페이스를 구현하면 JDK Dynamic Proxy 사용하여 프록시 인스턴스를 생성하며 반대로 객체가 특정 인터페이스를 구현하지 않고 있다면 CGLIB Proxy를 사용하여 프록시 인스턴스를 생성합니다.

4. AOP 적용

package sample.core.aop;

import org.springframework.stereotype.Service;

@Service
public class BoardServiceImpl implements BoardService {
    @Override
    public void getAllList() {
        long begin = System.currentTimeMillis();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("getAllList");

        System.out.println(System.currentTimeMillis() - begin);

    }

    @Override
    public void getKeyWordList() {
        long begin = System.currentTimeMillis();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("getKeyWordList!");

        System.out.println(System.currentTimeMillis() - begin);
    }
}

성능 테스트를 위해서 시간을 찍는 간단한 예제입니다. 보이는 것과 같이 중복된 코드들이 있고, 이것들은 다른 곳에도 쓰일 수 있다는 생각이 듭니다. 즉 이렇게 흩어진 관심사들을 AOP를 이용하여 하나의 관심사로 묶을 수 있다.

XML config

	<aop:aspect id="BoardService" ref="logAspect">
		<aop:pointcut id="prefLogPointCut" expression="execution(* sample.core.aop.BoardService.*(..))"/>
	</aop:aspect>
package sample.core.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogAspect {

    @Around("execution(* sample.core.aop.BoardService.*(..))") // pointcut
    // smaple.core.aop.BoardService 하위 메소드에 모두 적용
    public Object requestLog(ProceedingJoinPoint joinPoint) throws Throwable {
        long begin = System.currentTimeMillis();
        Object relVal = joinPoint.proceed();
        System.out.println(System.currentTimeMillis() - begin);

        return relVal;
    }
}

성능을 측정하는 코드를 하나의 Aspect 로 빼고 execution 을 통해 pointcut 을 주었습니다.

5. 결론

AOP를 이용하여 흩어진 관심사들을 하나로 모듈화시킴으로 중복된 로직을 제거할 수 있는 장점을 얻었다. 이를 통해 서두에 말했던 OOP를 보안 할 수 있는 프로그래밍 기법임과 동시에 비지니스 로직으로 부터 분리시켜 재사용성도 높일 수 있습니다.

profile
JAVA BACK_END DEVELOPER

0개의 댓글