danDevlog

[Spring Boot] AOP(Aspect Oriented Programming) 본문

Spring 입문

[Spring Boot] AOP(Aspect Oriented Programming)

단데기이 2022. 3. 27. 22:31
728x90

성능(시간)을 알아보기 위해 모든 메소드의 호출 시간을 측정하고 싶다면?

package hello.hellospring.service;
@Transactional
public class MemberService {
    /**
     * 회원가입
     */
    public Long join(Member member) {
        long start = System.currentTimeMillis();
        try {
            validateDuplicateMember(member); //중복 회원 검증
            memberRepository.save(member);
            return member.getId();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("join " + timeMs + "ms");
        }
    }
    /**
     * 전체 회원 조회
     */
    public List<Member> findMembers() {
        long start = System.currentTimeMillis();
        try {
            return memberRepository.findAll();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("findMembers " + timeMs + "ms");
        }
    }
}

위에 시간을 측정하는 코드들을 모든 함수에 일일이 적어줘야한다.

함수가 적으면 할만하겠지만, 함수가 수 천개이며, 밀리초 단위가아니라 다른 단위로 재야한다면?

일일이 적는데도 엄청난 시간이 소요되고, 수정도 일일이 다 해줘야한다.

 

그렇기에, 공통 관심 사항 과 핵심 관심 사항으로 분리해준다.

 

aop패키지를 생성한 후, TimeTraceAop클래스를 생성해준다.

package hello.hellospring.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 TimeTraceAop {

    // 경로(주소)를 지정해서 특정 패키지만 사용할수도 있다.
    // ex)execution(* hello.hellospring.service..*(..))")
    @Around("execution(* hello.hellospring..*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {

        long start = System.currentTimeMillis();

        System.out.println("START: " + joinPoint.toString());

        try{
            return joinPoint.proceed();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");
        }
    }
}

AOP를 사용하면 이 로직만 변경해주면 되고, 모든 함수에 추가할 필요 없이 이 클래스 하나로 모든 함수가 실행될 때마다 적용된다. 

 

스프링 컨테이너에서 memberController, memberService, memberRepository 각각이 실행되기 전에 

프록시 ~xx 가 실행된다. 즉 복제파일이라고 할수 있다.

실제로 proxy가 주입되는지 콘솔에 출력해서 확인해보면 복제된 객체의 주소값이 출력된다.

Comments