일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- Java
- 플러터
- spring
- SWEA
- C언어
- 페이코 추천인코드
- 페이코 초대코드
- 페이코 추천인
- 자바
- php 프로그래밍 입문 3판
- php
- 플러터 개발환경 설정
- php 프로그래밍 입문 솔루션
- 자바 스프링
- 배열
- php 프로그래밍 입문 문제풀이
- php 프로그래밍 입문 예제
- 페이코 친구코드
- C
- 백준
- php 프로그래밍 입문
- 최단 경로
- 스프링
- 파이썬
- Flutter
- programmers
- php 프로그래밍 입문 연습문제
- 한정 분기
- php 프로그래밍
- JAVA SPRING
- Today
- Total
ImJay
[Java Spring] 1-25. AOP 적용 본문
[Java Spring] 1-25. AOP 적용
1. 이러한 상황에 필요한 기술을 AOP (Aspect Oriented Programming) 라고 한다.
[Java Spring] 24. AOP가 필요한 상황
[Java Spring] 24. AOP가 필요한 상황 1. 모든 메소드의 호출 시간을 측정하고 싶다면? 직장 상사가 갑작스럽게 프로그램의 모든 메소드들의 호출 시간을 측정해오라는 업무지시를 한다. 프로그램에
develop247.tistory.com
2. 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern) 을 분리하는 기술을 말한다.
3. 시간 측정 로직을 한군데에 모으고, 내가 원하는 곳에 적용시키는 것을 가능하게 만드는게 AOP 이다.
4. main > java > hellospring 에 aop 하위 패키지 생성
5. aop 패키지 내에 TimeTraceAop 클래스 생성
6. 코드 작성
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 {
@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 는 Aspect 어노테이션이 필요하다.
- 연결을 위해 Component 어노테이션을 추가한다.
- Around() 어노테이션은 어떤 메소드에 실행을 적용할지 추가하는 부분이다.
상기 코드에서는 hellospring의 모든 부분에 적용된다.
7. 빌드 후 테스트를 진행해보자.
- 회원 목록에 접속하니, 해당 사이트에 접속하기 위해 호출한 메소드들과 그 메소드들의 호출 시간을 결과로 확인할 수 있다.
8. 해결
- 회원가입, 회원 조회등 핵심 관심사항과 시간을 측정하는 공통 관심 사항을 분리한다.
- 시간을 측정하는 로직을 별도의 공통 로직으로 만들었다.
- 핵심 관심 사항을 깔끔하게 유지할 수 있다.
- 변경이 필요하면 이 로직만 변경하면 된다.
- 원하는 적용 대상을 선택할 수 있다.
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Transactional
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
/**
* 회원 가입
*/
public Long join(Member member) {
validateDuplicateMember(member); //중복 회원 검증
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
}
/**
* 전체 회원 조회
*/
public List<Member> findMembers() {
return memberRepository.findAll();
}
public Optional<Member> findOne(Long memberId) {
return memberRepository.findById(memberId);
}
}
- 실제 MemberService 는 원래대로 돌아왔고, 깔끔하게 유지보수가 가능하며 측정 시간 외 기능을 추가할 때는 TimeTraceAop 클래스만 수정해주면 된다.
9. @Around 어노테이션 수정
- Around 어노테이션을 수정해서 내가 원하는 범위 내에서만 로직을 적용시킬 수도 있다.
10. 다시 빌드 후 테스트를 진행해보자.
- 실제 service 패키지 내에 있는 메소드들의 호출 시간만이 측정되어 출력되는 모습을 확인할 수 있다.
11. 작동원리
- 실제로 컨트롤러는 가상의 memberService 프록시를 호출한다.
- memberService 프록시를 호출 후 스프링 빈 호출이 끝나면, 그 때 proceed() 호출로 진짜 실제 memberService 를 호출해준다.
- 이는 간단한 코드를 추가하여 직접 확인해볼 수 있다.
- 실제 호출되는 클래스는 MemberService 가 아닌 SpringCGLIB 가 추가된 클래스임을 알 수 있다. 여기서 CGLIB 는 사용되는 라이브러리명이다.
12. 전체 의존관계
- 우리는 DI의 이점을 통해 AOP 기술을 사용할 수 있는 것이다.
'Java Spring > 스프링 입문' 카테고리의 다른 글
[Java Spring] 1-26. 마무리 (0) | 2023.01.30 |
---|---|
[Java Spring] 1-24. AOP가 필요한 상황 (1) | 2023.01.30 |
[Java Spring] 1-23. 스프링 데이터 JPA (0) | 2023.01.30 |
[Java Spring] 1-22. JPA (1) | 2023.01.30 |
[Java Spring] 1-21. JDBC Template (0) | 2023.01.30 |