스프링 AOP 실무 주의사항프록시와 내부 호출 - 문제스프링은 프록시 방식의 AOP를 사용한다.AOP 적용 시 스프링은 실제 객체 대신 프록시를 스프링 빈으로 등록한다.스프링은 의존관계 주입 시 항상 프록시 객체를 주입한다.AOP를 적용하기 위해서 항상 프록시를 통해서 실제 객체(Target)을 호출해야 한다.프록시에서 어드바이스를 호출하고 이후 실제 객체를 호출한다.프록시를 거치지않고 실제 객체를 직접 호출하면 AOP가 적용되지 않는다.실제 객체 내부에서 메소드 호출이 발생하면 프록시를 거치지 않고 실제 객체를 직접 호출하는 문제가 발생한다. @Slf4j@Componentpublic class CallServiceV0 { public void external() { log.info("..
스프링 AOP 실전 예제예제 만들기@Repositorypublic class ExamRepository { private static int seq = 0; /** * 5번에 1번 실패하는 요청 */ public String save(String itemId) { seq++; if (seq % 5 == 0) { throw new IllegalStateException("예외 발생"); } return "ok"; }}Repository 예제save()에서 요청이 5번 중 1번 예외 발생으로 실패한다. @Service@RequiredArgsConstructorpublic class ExamService ..
스프링 AOP - 포인트컷포인트컷 지시자AspectJ는 포인트컷을 편리하게 표현하기 위해 특별한 표현식을 제공한다.ex) @Pointcut("execution(* hello.aop.order..*(..))")포인트컷 표현식 = AspectJ가 제공하는 포인트컷 표현식 포인트컷 지시자(PCD) : 포인트컷 표현식에서 시작 부분을 의미포인트컷 지시자 종류execution : 메소드 실행 조인 포인트를 매칭한다. (가장 많이 사용하며 기능이 복잡)within : 특정 타입내의 조인 포인트를 매칭한다.args : 인자가 주어진 타입의 인스턴스 조인 포인트this : 스프링 빈 객체(프록시)를 대상으로 하는 조인 포인트target : Target 객체(원본 객체)를 대상으로 하는 조인 포인트@target : 실행..
스프링 AOP스프링 AOP 구현@Slf4j@Aspectpublic class AspectV1 { @Around("execution(* hello.aop.order..*(..))") public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable { log.info("[log] {}", joinPoint.getSignature()); //join point 시그니처 return joinPoint.proceed(); }}@Aspect를 사용해 AOP 구현@Around 어노테이션 값은 포인트컷이 된다.AspectJ 포인트컷 표현식 사용"execution ~ " : hello.aop.order 패키지 및 하위 패키..
스프링 AOPAOP 소개 - 핵심 기능과 부가 기능애플리케이션 로직은 핵심 기능과 부가 기능으로 나눌 수 있다.핵심 기능 : 해당 객체가 제공하는 고유 기능이다.ex) 주문 로직 기능부가 기능 : 단독으로 사용되지 않고 핵심 기능을 보조하기 위해 제공되는 기능이다.ex) 트랜잭션 기능, 로그 추적 기능 여러 곳에서 공통으로 사용하는 부가 기능의 경우 횡단 관심사(cross-cutting concerns)가 된다. 부가 기능 적용 시 반복, 중복 코드, 수정으로 많은 문제가 발생한다.AOP 소개 - AspectAspect : 핵심 기능과 부가 기능을 분리해서 한 곳에서 관리하도록 하고 부가 기능과 해당 부가 기능을 어디에 적용할지 정의한 것@Aspect, 스프링이 제공하는 Advisor도 하나의 Aspec..
@Aspect AOP@Aspect 프록시 - 적용스프링 애플리케이션에 프록시 적용 시 어드바이저(포인트컷+어드바이스)를 만들어서 스프링 빈으로 등록하면 된다.나머지는 자동 프록시 생성기(빈 후처리기)가 스프링 빈으로 등록된 어드바이저들을 찾고 스프링 빈들에 자동으로 프록시를 적용함으로 모두 처리해준다. 스프링은 @Aspect 어노테이션으로 매우 편리하게 어드바이져 생성 기능을 지원한다.@Aspect는 관점 지향 프로그래밍(AOP)을 가능하게 하는 AspectJ 프로젝트에서 제공하는 어노테이션이다. @Slf4j@Aspectpublic class LogTraceAspect { private final LogTrace logTrace; public LogTraceAspect(LogTrace logT..
빈 후처리기빈 후처리기 - 소개@Bean이나 컴포넌트 스캔으로 스프링 빈을 등록하는 경우스프링은 대상 객체를 생성스프링 컨테이너 내부의 빈 저장소에 등록이후 스프링 컨테이너를 통해 등록된 스프링 빈을 조회해서 사용빈 후처리기 - BeanPostProcessor스프링이 빈 저장소에 등록할 목적으로 생성한 객체를 빈 저장소에 등록하기 직전 조작하기 위한 것이다.빈을 생성한 후 무언가를 처리하기 위한 용도로 사용한다.객체를 조작할 수도 있고, 완전히 다른 객체로 바꿔치기 하는 것도 가능하다. 빈 후처리기 과정생성 : 스프링 빈 대상이 되는 객체를 생성한다.(@Bean, 컴포넌트 스캔 포함)전달 : 생성된 객체를 빈 저장소에 등록하기 전 빈 후처리기에 전달한다.후 처리 작업 : 빈 후처리기는 전달된 스프링 빈 ..
프록시 팩토리이전에는 상황에 따라서 인터페이스가 있으면 JDK 동적 프록시를 사용하고 구체 클래스의 경우 CGLIB를 사용했다면 프록시 팩토리 하나로 동적 프록시를 생성할 수 있다.프록시 팩토리 : 스프링에서 제공하는 동적 프록시를 통합해서 편리하게 만들어주는 기능이다.동작 방식 - 인터페이스가 있으면 JDK 동적 프록시를 사용, 구체 클래스만 있으면 CGLIB를 사용한다.부가 기능 적용 시 Advice를 만들면 InvocationHandler나 MethodInterceptor를 신경쓰지않아도 된다.프록시 팩토리를 사용하면 Advice를 호출하는 전용 (스프링에서 제공) InvocationHandler, MethodInterceptor를 내부에서 사용 Advice 동작 흐름클라이언트가 프록시 팩토리에게 ..
동적 프록시 기술리플렉션프록시를 사용하기 위해서 프록시 클래스를 별도로 만들지 않더라도 자바에서 제공하는 JDK 동적 프록시 기술이나 CGLIB같은 프록시 생성 오픈소스 기술을 활용하면 프록시 객체를 동적으로 만들어낼 수 있다. 리플렉션 기술 : 클래스나 메소드의 메타정보를 동적으로 획득하고 코드도 동적으로 호출할 수 있는 기술이다. @Slf4jpublic class ReflectionTest { @Test public void reflection0() { Hello target = new Hello(); //공통 로직1 시작 log.info("start"); String result1 = target.callA(); //호출하는 메소드가 다름..
예제 프로젝트 만들기예제 프로젝트 종류v1 - 인터페이스와 구현 클래스 (스프링 빈 수동 등록)v2 - 인터페이스 없는 구체 클래스 (스프링 빈 수동 등록)v3 - 컴포넌트 스캔 (스프링 빈 자동 등록)실무에서 스프링 빈으로 등록할 클래스는 인터페이스가 있는 경우도 없는 경우도 있다.스프링 빈으로 직접 등록하는 경우도, 컴포넌트 스캔으로 자동 등록하는 경우도 있다.예제 프로젝트 만들기 - v1public interface OrderRepositoryV1 { void save(String itemId);}public class OrderRepositoryV1Impl implements OrderRepositoryV1 { @Override public void save(String itemI..