스프링 입문(코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술) - AOP

밀크야살빼자·2023년 4월 19일
0

AOP가 필요한 상황

  • 모든 메소드의 호출 시간을 측정하고 싶을때
  • 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern)
  • 회원 가입 시간, 회원 조회 시간을 측정하고 싶을때

service/MemberService

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;

import java.util.List;
import java.util.Optional;

public class MemberService {

    private final MemberRepository memberRepository;


    public MemberService(MemberRepository memberRepository){
        this.memberRepository = memberRepository;
    }

    /**
     * 회원 가입
     * @param member
     * @return
     */
    public Long join(Member member){
        //같은 이름이 있는 중복 회원X
        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");
       }
    }

    private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
            .ifPresent(m -> {
            throw new IllegalStateException("이미 존재하는 회원입니다.");
        });
    }
    /*
    *전체 회원 조회
     */
    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");
        }

    }

    public Optional<Member> findOne(Long memberId){
        return memberRepository.findById(memberId);
    }
}
  • 문제
    • 회원가입, 회원 조회에 시간을 측정하는 기능은 핵심 관심 사항이 아니다.
    • 시간을 측정하는 로직은 공통 관심 사항이다.
    • 시간을 측정하는 로직과 핵심 비즈니스의 로직이 섞여서 유지보수가 어렵다.
    • 시간을 측정하는 로직을 별도의 공통 로직으로 만들기 매우 어렵다.
    • 시간을 측정하는 로직을 변경할 때 모든 로직을 찾아가면서 변경해야 한다. -> 모든 메소드에 시간 측정 메소드를 작성해야 한다.

AOP 적용

  • AOP : Aspect Oriented Programming
  • 공통 관심 사항 vs 핵심 관심 사항 분리
  • 시간 측정 메소드를 한 곳에 다 모은 후에 원하는 곳에 공통 관심 사항을 적용한다.
@Component
@Aspect // 이것을 써야 aop를 쓸 수 있음
public class TimeTraceAop {
    @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 적용 전에는 helloController(helloController가 memberService를 호출하고 있음) 에서 memberService를 의존관계에 의해서 호출 했다면, 적용 후에는 helloController에서 memberService를 호출 하게 되면 가짜 memberService를 만들어서 스프링 컨테이너가 동작하면 진짜 스프링 빈을 등록을 안하고 가짜 스프링 빈을 등록한다. 가짜 스프링빈이 끝나면 joinPoint.proceed()를 통해 진짜를 호출한다.
profile
기록기록기록기록기록

0개의 댓글