Back-End 42

스프링 고급편 - 포인트컷

✔️ 포인트컷 지시자(Pointcut Designator) : PCD애스팩트J는 포인트 컷을 편리하게 표현하기위한 특별한 표현식을 제공@Pointcut("execution(* hello.aop.order..*(..))")execution : 메서드 실행 조인 포인트를 매칭within : 특정 타입 내의 조인 포인트를 매칭args : 인자가주어진 타입의 인스턴스인 조인 포인트  this : 스프링 빈 객체(스프링 AOP 프록시)를 대상으로 하는 조인 포인트 target : Target 객체(스프링 AOP 프록시가 가리키는 실제 대상)를 대상으로 하는 조인 포인트@target : 실행 객체의클래스에주어진 타입의 애노테이션이 있는 조인 포인트    @within : 주어진 애노테이션이있는 타입 내 조인 포인트..

스프링 고급편 - 스프링 AOP 구현

✔️ 구현@Slf4j@Aspectpublic class AspectV1 { @Around("execution(* hello.aop.order..*(..))") public Object doLog(ProceedingJoinPoint joinPoint) throws Throwable { log.info("[log] {}", joinPoint.getSignature()); return joinPoint.proceed(); }}AspectV1을 만든다. @Around : 포인트 컷 부분에 해당* 모든 타입, hello.aop.order 패키지와 그 하위 패키지(..)를 지정 // 자세한건 다음 포스트에서 설명@Around가 달린 메서드 doLog는 어드바이스가 된다.  ..

스프링 고급편 - 스프링 AOP 개념

✔️ AOP - 핵심 기능과 부가 기능핵심 기능해당 객체가 제공하는 고유의 기능 (주문 로직 같은 target의 기능)  부가 기능핵심 기능을 보조하기 위해 제공되는 기능 (로그 추적 로직, 트랜잭션)이러한 부가 기능은 단독으로 사용되지 않고, 핵심 기능과 함께 사용  보통 부가 기능은 여러 클래스에 걸쳐서 함께사용된다.  부가기능 적용 문제 그런데 여러 곳에부가 기능을 적용하기에는 각 클래스 마다 동일한 코드를 추가해야하기에 번거롭다. 부가 기능이 구조적으로 단순 호출이 아닌 try-cath-finally 같은 구조가 필요하다면 더욱 복잡해진다.부가 기능 수정이 발생하면 적용한 모든 클래스를 수정해야한다. (끔찍하다..)  정리부가 기능을 적용할 때 아주 많은 반복이 필요부가 기능이 여러 곳에 퍼져서 ..

스프링 고급편 - @Aspect AOP

✔️ @Aspect 프록시스프링은 @Aspect 애노테이션으로 매우 편리하게 포인트 컷과 어드바이스로 구성되어있는 어드바이저 생성 기능 지원  참고@Aspect 는 관점 지향 프로그래밍(AOP)을 가능하게 하는 AspectJ 프로젝트에서 제공하는 애노테이션이다.   @Slf4j@Aspectpublic class LogTraceAspect { private final LogTrace logTrace; public LogTraceAspect(LogTrace logTrace) { this.logTrace = logTrace; } @Around("execution(* hello.proxy.app..*(..))") // 포인트 컷 public Object execute(Pr..

스프링 고급편 - 빈 후처리기

✔️ 빈 후처리기 - BeanPostProcessor스프링이 빈 저장소에 등록할 목적으로 생성한 객체를 빈 저장소에 등록하기 직전에조작이 가능하다.한 마디로 빈 생성후무언가 처리하는 용도이다.  이를 사용하면 컴포넌트 스캔 대상들도 프록시로 등록할 수 있게 된다.      BeanPostProcessor 인터페이스 - 스프링 제공public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException Object postProcessAfterInitialization(Object bean, String beanName) throws Bean..

스프링 고급편 - 스프링이 지원하는 프록시 (프록시 팩토리)

✔️ 프록시 팩토리 스프링은 동적 프록시를 통합해서 편리하게 만들어주는 프록시 팩토리(ProxyFactory) 기능을 제공프록시 팩토리 하나로인터페이스의 경우 JDK 동적 프록시를,구체 클래스의경우CGLIB를 적용해준다.  그런데 동적 프록시는 InvocationHandler가 , CGLIB는 MethodInterceptor 로 부가기능을 적용하였는데 프록시팩토리를 사용해도따로 만들어야할까? 스프링은 이 문제를 해결하기 위해 부가기능을 적용할 때 Advice   라는 새로운 개념을 도입했다.프록시 팩토리를 사용하면 Advice를 호출하는 전용 InvocationHandler, MethodInterceptor 를 내부에서 사용한다.   Advice 만들기Advice는 프록시에 적용하는부가 기능 로직이며,I..

스프링 고급편 - 동적 프록시 기술

핵심 내용만 정리하고  자세한 구현 코드는 올리지 않는다. 스프링 부트 3.3.3 버전 기준 ✔️ 리플렉션 이전까지 프록시를 사용해 로그 추적기 부가 기능을 적용했지만 대상 클래스만큼 프록시 클래스를 만들어야 한다는 단점이 있다.따라서 자바의 기본 제공 기술인 JDK 동적 프록시, CGLIB 같은 프록시 생성 오픈소스 기술을 활용하면 프록시 객체를 동적으로 만들어 낼 수 있다. 하지만 JDK 동적 프록시 생성을 이해하려면 리플렉션을 알아야한다. 리플렉션은 한다미로 메타 데이터 이다. void reflection1() throws Exception { //클래스 정보 Class classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hell..

스프링 고급편 - 프록시 패턴과 데코레이터 패턴

✔️ 프록시 패턴  프록시는 대체자 이다.프록시의 주요 기능접근 제어권한에 따른 접근 차단캐싱지연 로딩부가 기능 추가원래 서버가 제공하는 기능에 더해서 부가 기능을 수행예) 요청 값이나, 응답 값을 중간에 변형예) 실행 시간을 측정해서 추가 로그를 남김프록시는 체인 작용이 가능하다.     GOF 디자인 패턴둘다 프록시를 사용하지만 의도에 따라서 프록시 패턴과 데코레이터 패턴으로 구분프록시 패턴 : 접근 제어가 목적데코레이터 패턴 : 새로운 기능 추가가 목적위 그림을 보면클라이언트가 subject에 접근하지만 subject의 구현체인 proxy가 캐시 처리를 하고없다면 target으로 realSubject를 이용해서 처리package hello.proxy.pureproxy.proxy.code;import..

스프링 고급편 - 템플릿 메서드 패턴과 콜백 패턴

✔️ 템플릿 메서드 패턴이전에 만들었던 로그 추적기를 더 향상시켜보자 템플릿 메서드 패턴은 변하지 않는 부분과 변하는 부분을 분리해서 변하지않는 부분을 템플릿(기본 틀)로 정의하고, 변하는 부분은 하위 클래스에서 정의하는 패턴이다.  로그 추적기의 변하지 않는 부분TraceStatus status = null;try { status = trace.begin("message"); //핵심 기능 호출 trace.end(status);} catch (Exception e) { trace.exception(status, e); throw e;}이 부분을 템플릿으로 정의한다. 추상 템플릿 클래스public abstract class AbstractTemplate { private final LogTrace ..

스프링 고급편 - 쓰레드 로컬 ThreadLocal

✔️ 전 시간 필드 동기화에 대하여매번 파라미터로 TraceId를 넘기는 것은 복잡하고 어렵다. 따라서 LogTrace 인터페이스를 만들고 traceHolder를 만들어서 여기에 traceId를 보관하여 동기화 한다.하지만 동시성 이슈가 발생한다. 결론적으로는 쓰레드 로컬을 사용하면 동시성 이슈도 해결된다.   먼저 TraceId를 파라미터로 넘기지 않고 필드 동기화하는 법이다.public interface LogTrace { TraceStatus begin(String message); void end(TraceStatus status); void exception(TraceStatus status, Exception e);} @Slf4jpublic class FieldLogTrace ..