Home

0

Spring 핵심원리 고급편 - 여러 Advisor 와 함께 적용

목차 BeanPostProcessor - 하나의 프록시에 여러개의 Advisor 적용 BeanPostProcessor Spring 핵심원리 고급편 - ProxyFactory 적용 Spring 핵심원리 고급편 - 여러 Advisor 와 함께 적용 Spring 핵심원리 고급편 - Spring 에서 제공하는 Pointcut Spring 핵심원리 고급편 - Pointcut 만들기 Spring 핵심원리 고급편 - Advisor Spring 핵심원리 고급편 - MethodInterceptor Spring 핵심원리 고급편 - ProxyFactory 참고본 포스트는 김영한의 스프링 핵심 원리 - 고급편 내용을 참고해 만들었습니다. 여러 Advisor 와 함께 적용 하나의 Target 에 여러 Advisor 를 적용한다. // 여러개의 프록시 객체// client -> proxy2(advisor2) -> proxy1(advisor1) -> target// Proxy 1 생성ServiceInterface target = new ServiceImpl();ProxyFactory proxyFactory = new ProxyFactory(target);// Advisor 인터페이스의 가장 일반적인 구현체DefaultPointcutAdvisor advisor1 = new DefaultPointcutAdvisor(Pointcut.TRUE, new Advice1());// ProxyFactory 에 적용할 Advisor 를 지정한다.proxyFactory.addAdvisor(advisor1);ServiceInterface proxy = (ServiceInterface) proxyFactory.getProxy();/////////////////////////////////////////////////////////////////////////////////////////////// Proxy 2 생성 (taget -> proxy 1 입력)ProxyFactory proxyFactory2 = new ProxyFactory(proxy);// Advisor 인터페이스의 가장 일반적인 구현체DefaultPointcutAdvisor advisor2 = new DefaultPointcutAdvisor(Pointcut.TRUE, new Advice2());// ProxyFactory 에 적용할 Advisor 를 지정한다.proxyFactory2.addAdvisor(advisor2);ServiceInterface proxy2 = (ServiceInterface) proxyFactory2.getProxy();proxy2.save(); 00:36:05.734 [Test worker] INFO hello.proxy.advisor.MultiAdvisorTest$Advice2 - advice2 호출00:36:05.737 [Test worker] INFO hello.proxy.advisor.MultiAdvisorTest$Advice1 - advice1 호출00:36:05.737 [Test worker] INFO hello.proxy.common.service.ServiceImpl - save 호출 하나의 프록시로 여러개의 Advisor 적용 위에서는 여러 Advisor 를 적용하기 위해서는 여러개의 프록시를 생성 해야 한다는 문제점이 있다.스프링 AOP 에서는 하나의 프록시만 생성 하고 여러개의 Advisor 를 적용 할 수 있도록 지원한다.

0

Spring 핵심원리 고급편 - Spring 에서 제공하는 Pointcut

목차 BeanPostProcessor - 하나의 프록시에 여러개의 Advisor 적용 BeanPostProcessor Spring 핵심원리 고급편 - ProxyFactory 적용 Spring 핵심원리 고급편 - 여러 Advisor 와 함께 적용 Spring 핵심원리 고급편 - Spring 에서 제공하는 Pointcut Spring 핵심원리 고급편 - Pointcut 만들기 Spring 핵심원리 고급편 - Advisor Spring 핵심원리 고급편 - MethodInterceptor Spring 핵심원리 고급편 - ProxyFactory 참고본 포스트는 김영한의 스프링 핵심 원리 - 고급편 내용을 참고해 만들었습니다. save 메서드는 어드바이스 로직을 적용하지만, find 메서드에서는 어드바이스 로직을 적용하지 않도록 설정하기 Spring 에서 제공하는 Pointcut 가장 많이 사용하는 Pointcut 구현체는 AspectJExpressionPointcut 다. 클래스 설명 NameMatchMethodPointcut 메서드 이름을 기반으로 매칭한다. 내부적으로 PatternMatchUtils 을 사용한다. JdkRegexpMethodPointcut JDK 정규 표현식을 기반으로 포인트 컷을 한다. AnnotationMatchingPointcut 애노테이션으로 매칭한다. AspectJExpressionPointcut aspectJ 표현식으로 매칭한다. ServiceInterface target = new ServiceImpl();ProxyFactory proxyFactory = new ProxyFactory(target);// Spring 에서 제공하는 PointcutNameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();pointcut.setMappedNames("save");// Advisor 인터페이스의 가장 일반적인 구현체DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, new TimeAdvice());// ProxyFactory 에 적용할 Advisor 를 지정한다.proxyFactory.addAdvisor(advisor);ServiceInterface proxy = (ServiceInterface) proxyFactory.getProxy();proxy.save();proxy.find(); 00:14:12.347 [Test worker] INFO hello.proxy.common.advice.TimeAdvice - TimeProxy 실행00:14:12.349 [Test worker] INFO hello.proxy.common.service.ServiceImpl - save 호출00:14:12.349 [Test worker] INFO hello.proxy.common.advice.TimeAdvice - TimeProxy 종료 resultTime = 000:14:12.351 [Test worker] INFO hello.proxy.common.service.ServiceImpl - find 호출

0

Spring 핵심원리 고급편 - Pointcut 만들기

목차 BeanPostProcessor - 하나의 프록시에 여러개의 Advisor 적용 BeanPostProcessor Spring 핵심원리 고급편 - ProxyFactory 적용 Spring 핵심원리 고급편 - 여러 Advisor 와 함께 적용 Spring 핵심원리 고급편 - Spring 에서 제공하는 Pointcut Spring 핵심원리 고급편 - Pointcut 만들기 Spring 핵심원리 고급편 - Advisor Spring 핵심원리 고급편 - MethodInterceptor Spring 핵심원리 고급편 - ProxyFactory 참고본 포스트는 김영한의 스프링 핵심 원리 - 고급편 내용을 참고해 만들었습니다. Pointcut 인터페이스 Pointcut 은 getClassFilter 메서드와 getMethodMatcher 메서드를 이용해 필터링 을 진행한다.둘다 TRUE 를 반환해야 Advice 를 적용할 수 있다 getClassFilter : Class 조건으로 Filter 하는 메서드 .getMethodMatcher : Method 조건으로 Filter 하는 메서드 public interface Pointcut { // 클래스 조건으로 필터링 ClassFilter getClassFilter(); // 메서드 조건으로 필터링 MethodMatcher getMethodMatcher(); Pointcut TRUE = TruePointcut.INSTANCE;} Pointcut 적용하기 save 메서드는 Advice 로직을 적용하지만, find 메서드에서는 Advice 로직을 적용하지 않도록 설정하기

0

Spring 핵심원리 고급편 - Advisor

목차 BeanPostProcessor - 하나의 프록시에 여러개의 Advisor 적용 BeanPostProcessor Spring 핵심원리 고급편 - ProxyFactory 적용 Spring 핵심원리 고급편 - 여러 Advisor 와 함께 적용 Spring 핵심원리 고급편 - Spring 에서 제공하는 Pointcut Spring 핵심원리 고급편 - Pointcut 만들기 Spring 핵심원리 고급편 - Advisor Spring 핵심원리 고급편 - MethodInterceptor Spring 핵심원리 고급편 - ProxyFactory 참고본 포스트는 김영한의 스프링 핵심 원리 - 고급편 내용을 참고해 만들었습니다. Advisor Advisor는 Spring AOP에서 Advice, Pointcut, Advisor의 개념을 쉽게 사용할 수 있도록 제공합니다. Advice 는 메소드를 실행하기 전, 후, 혹은 예외가 발생했을 때 실행되는 부가 기능을 말하며, Pointcut 은 Advice가 적용될 메소드를 선택하는 기준입니다. Advisor 는 Advice 와 Pointcut 을 결합한 것으로, 어떤 메소드에 어떤 Advice 를 적용할지를 결정합니다. PointCut (포인트 컷) 어디에 부가 기능을 적용할지 적용하지 않을지 판단하는 필터링 로직 클래스 이름과 메서드 이름을 이용해 필터링 한다. Advice (어드바이스) 프록시가 호출하는 부가 기능 Advisor (어드바이저) 단순하게 하나의 포인트 컷 과 하나의 어드바이스 를 갖고 있는 것 DefaultPointcutAdvisor

0

Spring 핵심원리 고급편 - CGLIB

목차 Spring 핵심원리 고급편 - CGLIB Spring 핵심원리 고급편 - Dynamic Proxy 2 Spring 핵심원리 고급편 - Dynamic Proxy 1 Spring 핵심원리 고급편 - 리플렉션 Spring 핵심원리 고급편 - 구체 클래스 기반 프록시 적용 2 Spring 핵심원리 고급편 - 구체 클래스 기반 프록시 Spring 핵심원리 고급편 - 인터페이스 프록시 1 Spring 핵심원리 고급편 - Decorator Pattern 2 Spring 핵심원리 고급편 - Decorator Pattern 1 Spring 핵심원리 고급편 - Proxy 패턴 컴포넌트 스캔으로 자동 빈 등록 Spring 핵심원리 고급편 - Proxy 패턴 인터페이스 없는 없는 구체 클래스 Spring 핵심원리 고급편 - Proxy 패턴 인터페이스와 구체 클래스 Spring 핵심원리 고급편 - Proxy 패턴 Spring 핵심원리 고급편 - Strategy 패턴 Spring 핵심원리 고급편 - Template Method 패턴 참고 https://www.baeldung.com/cglib Dynamic Proxy 의 한계와 CGLIBDynamic Proxy 의 경우 인터페이스를 구현한 클래스에 대해서만 프록시 객체를 생성할 수 있습니다. 그렇다면 인터페이스가 없는 클래스의 경우 프록시 생성을 못하냐? 아닙니다. 자바에서는 인터페이스를 구현하지 않은 클래스에 대해서도 프록시 객체를 생성할 수 있도록 CGLIB 를 제공합니다. 차이점은 Dynamic Proxy 는 인터페이스 구현을 통해 프록시 객체를 생성하지만 CGLIB 는 상속 을 통해 프록시 객체를 생성한다는 것입니다. CGLIB 란? CGLIB 는 Code Generation Library의 약자로 런타임 시 Java 바이트 코드 를 조작해 동적으로 클래스를 생성하는 라이브러리 JDK Dynamic 프록시와는 다르게 구체 클래스 만 갖고도 동적으로 Proxy 를 생성할 수 있다. CGLIB은 자바의 리플렉션(Reflection) API 와 바이트코드 조작(Bytecode Manipulation) 기술을 이용하여 클래스의 상속 구조를 이용해서 프록시 객체를 생성합니다. 이 과정에서 바이트코드를 조작하므로, JVM의 클래스 로딩 과정에서 원본 클래스의 바이트코드를 변경할 수 있습니다.

0

Spring 핵심원리 고급편 - MethodInterceptor

목차 BeanPostProcessor - 하나의 프록시에 여러개의 Advisor 적용 BeanPostProcessor Spring 핵심원리 고급편 - ProxyFactory 적용 Spring 핵심원리 고급편 - 여러 Advisor 와 함께 적용 Spring 핵심원리 고급편 - Spring 에서 제공하는 Pointcut Spring 핵심원리 고급편 - Pointcut 만들기 Spring 핵심원리 고급편 - Advisor Spring 핵심원리 고급편 - MethodInterceptor Spring 핵심원리 고급편 - ProxyFactory 참고본 포스트는 김영한의 스프링 핵심 원리 - 고급편 내용을 참고해 만들었습니다. MethodInterceptor - 부가기능 구현Spring 에서는 프록시 객체에 부가기능을 적용하기 위해 MethodInterceptor 인터페이스를 제공합니다. MethodInterceptor 인터페이스 구현을 통해 프록시 객체에 적용될 부가기능을 생성할 수 있습니다. MethodInterceptor 인터페이스 내 invoke 메소드 인자 MethodInvocation 객체에는 다음 메서드를 호출하는 방법, 현재 프록시 객체 인스턴스, args, 메서드 정보등이 표함돼 있다. CGLIB 에서 제공하는 MethodInterceptor 와 이름이 비슷하므로 구현시 주의할 필요가 있습니다. package org.aopalliance.intercept;public interface MethodInterceptor extends Interceptor { Object invoke(MethodInvocation invocation) throws Throwable; }

0

Spring 핵심원리 고급편 - ProxyFactory

목차 BeanPostProcessor - 하나의 프록시에 여러개의 Advisor 적용 BeanPostProcessor Spring 핵심원리 고급편 - ProxyFactory 적용 Spring 핵심원리 고급편 - 여러 Advisor 와 함께 적용 Spring 핵심원리 고급편 - Spring 에서 제공하는 Pointcut Spring 핵심원리 고급편 - Pointcut 만들기 Spring 핵심원리 고급편 - Advisor Spring 핵심원리 고급편 - MethodInterceptor Spring 핵심원리 고급편 - ProxyFactory 참고본 포스트는 김영한의 스프링 핵심 원리 - 고급편 내용을 참고해 만들었습니다. Spring 에서의 ProxyFactory Spring 에서는 프록시 객체를 생성하기 위해 ProxyFactory 를 제공합니다. Spring에서 ProxyFactory 는 프록시 객체를 생성하는 팩토리입니다. ProxyFactory 는 인터페이스가 있을 때는 JDK 동적 프록시 를 사용해 프록시 객체를 생성하고 인터페이스가 없을 경우에는 CGLIB 를 사용해 프록시 객체를 생성합니다. Advice Advice 는 프록시에 적용하는 부가 기능 로직 이다.JDK 동적 프록시 가 제공하는 InvocationHandler 와 CGLIB 가 제공하는 MethodInterceptor 의 개념과 유사하다.

0

JPA 연관 관계 - 상속 관계 Mapping

목차 JPA 연관 관계 - 고아 객체 JPA 연관 관계 - 즉시로딩과 지연로딩 JPA 연관 관계 - 프록시 객체 JPA 연관 관계 - @MappedSuperclass JPA 연관 관계 - 상속 관계 Mapping JPA 연관 관계 - 영속성 전이 Cascade JPA 연관 관계 - 양방향 연관관계와 연관과계의 주인 JPA 연관 관계 - 양방향 연관관계 JPA 연관 관계 - 객체 지향 스럽게 모델링 하기 JPA 연관 관계 - 객체 관계 모델링하기 JPA 연관 관계 JPA 상속 관계 Mapping 관계형 데이터 베이스는 상속 관계가 없다. 슈펴타입 서브타입 관계라는 모델링 기법이 객체의 상속과 유사하다. 상속관계 Mapping : 객체의 상속 관계와 DB 의 슈퍼타입 서브타입 관계를 Mapping 슈퍼타입 서브타입 논리 모델을 객체의 상속관계를 물리 모델로 구현하는 방법 객체의 상속관계를 슈퍼타입 서브타입 모델로 구현하는 방법은 3가지 방법이 있다. 전략 설명 조인 전략 각각 테이블로 변환 (연관 관계로 관리) 단일 테이블 전략 통합 테이블로 변환 (하나의 테이블로 관리) 구현 클래스마다 테이블 전략 서브타입 테이블로 변환 사용하는 어노테이션 @Inheritance @DiscriminatorColumn(name=”DTYPE”) @DiscriminotorValue @Inheritance 전략

0

Spring 핵심원리 고급편 - Dynamic Proxy 2

목차 Spring 핵심원리 고급편 - CGLIB Spring 핵심원리 고급편 - Dynamic Proxy 2 Spring 핵심원리 고급편 - Dynamic Proxy 1 Spring 핵심원리 고급편 - 리플렉션 Spring 핵심원리 고급편 - 구체 클래스 기반 프록시 적용 2 Spring 핵심원리 고급편 - 구체 클래스 기반 프록시 Spring 핵심원리 고급편 - 인터페이스 프록시 1 Spring 핵심원리 고급편 - Decorator Pattern 2 Spring 핵심원리 고급편 - Decorator Pattern 1 Spring 핵심원리 고급편 - Proxy 패턴 컴포넌트 스캔으로 자동 빈 등록 Spring 핵심원리 고급편 - Proxy 패턴 인터페이스 없는 없는 구체 클래스 Spring 핵심원리 고급편 - Proxy 패턴 인터페이스와 구체 클래스 Spring 핵심원리 고급편 - Proxy 패턴 Spring 핵심원리 고급편 - Strategy 패턴 Spring 핵심원리 고급편 - Template Method 패턴 public class LogTraceBasicHandler implements InvocationHandler { private final Object target; private final LogTrace logTrace; public LogTraceBasicHandler(Object target, LogTrace logTrace) { this.target = target; this.logTrace = logTrace; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { TraceStatus status = null; try { String message = method.getDeclaringClass().getSimpleName() + "." + method.getName() + "()"; status = logTrace.begin(message); // 로직 호출 method.invoke(target, args); logTrace.end(status); return result; } catch (Exception ex) { logTrace.exception(status, ex); throw ex; } }} @Configurationpublic class DynamicBasicProxyConfig { @Bean public OrderControllerV1 orderControllerV1(LogTrace logTrace){ OrderControllerV1 orderControllerV1 = new OrderControllerV1Impl(orderServiceV1(logTrace)); // Proxy 객체 생성 OrderControllerV1 proxy = (OrderControllerV1) Proxy .newProxyInstance( OrderControllerV1.class.getClassLoader(), new Class[]{OrderControllerV1.class}, new LogTraceBasicHandler(orderControllerV1, logTrace)); return proxy; } @Bean public OrderServiceV1 orderServiceV1(LogTrace logTrace){ OrderServiceV1 orderServiceV1 = new OrderServiceV1Impl(orderRepositoryV1(logTrace)); // Proxy 객체 생성 OrderServiceV1 proxy = (OrderServiceV1) Proxy .newProxyInstance( OrderServiceV1.class.getClassLoader(), new Class[]{OrderServiceV1.class}, new LogTraceBasicHandler(orderServiceV1, logTrace)); return proxy; } @Bean public OrderRepositoryV1 orderRepositoryV1(LogTrace logTrace){ OrderRepositoryV1 orderRepository = new OrderRepositoryV1Impl(); // Proxy 객체 생성 OrderRepositoryV1 proxy = (OrderRepositoryV1) Proxy .newProxyInstance( OrderRepositoryV1.class.getClassLoader(), new Class[]{OrderRepositoryV1.class}, new LogTraceBasicHandler(orderRepository, logTrace)); return proxy; }} @Import(DynamicBasicProxyConfig.class)@SpringBootApplication(scanBasePackages = "hello.proxy.app") //주의public class ProxyApplication { public static void main(String[] args) { SpringApplication.run(ProxyApplication.class, args); } @Bean public LogTrace logTrace(){ return new ThreadLocalLogTrace(); }} 2021-11-28 22:18:58.331 INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace : [4e72efcd] OrderControllerV1.request()2021-11-28 22:18:58.333 INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace : [4e72efcd] |-->OrderServiceV1.orderItem()2021-11-28 22:18:58.333 INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace : [4e72efcd] | |-->OrderRepositoryV1.save()2021-11-28 22:18:59.338 INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace : [4e72efcd] | |<--OrderRepositoryV1.save() time=1005ms2021-11-28 22:18:59.338 INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace : [4e72efcd] |<--OrderServiceV1.orderItem() time=1006ms2021-11-28 22:18:59.339 INFO 3357 --- [nio-8080-exec-1] h.p.trace.logtrace.ThreadLocalLogTrace : [4e72efcd] OrderControllerV1.request() time=1007ms 특정 메소드에만 부가기능 로직 적용PatternMatchUtils.simpleMatch 를 사용해 메소드 이름이 조건을 만족하는지 Pattern Matching 한다.

0

Spring 핵심원리 고급편 - Dynamic Proxy 1

목차 Spring 핵심원리 고급편 - CGLIB Spring 핵심원리 고급편 - Dynamic Proxy 2 Spring 핵심원리 고급편 - Dynamic Proxy 1 Spring 핵심원리 고급편 - 리플렉션 Spring 핵심원리 고급편 - 구체 클래스 기반 프록시 적용 2 Spring 핵심원리 고급편 - 구체 클래스 기반 프록시 Spring 핵심원리 고급편 - 인터페이스 프록시 1 Spring 핵심원리 고급편 - Decorator Pattern 2 Spring 핵심원리 고급편 - Decorator Pattern 1 Spring 핵심원리 고급편 - Proxy 패턴 컴포넌트 스캔으로 자동 빈 등록 Spring 핵심원리 고급편 - Proxy 패턴 인터페이스 없는 없는 구체 클래스 Spring 핵심원리 고급편 - Proxy 패턴 인터페이스와 구체 클래스 Spring 핵심원리 고급편 - Proxy 패턴 Spring 핵심원리 고급편 - Strategy 패턴 Spring 핵심원리 고급편 - Template Method 패턴 JDK 동적 프록시 JDK 동적 프록시는 인터페이스 를 기반으로 프록시 를 동적으로 만들어준다.JDK 동적 프록시는 자바 리플렉션(Reflection) 을 이용하여 런타임 시에 인터페이스를 구현하는 프록시 객체 를 생성하는 기술 동적 프록시 기술을 사용하면 개발자가 직접 Proxy 클래스를 생성할 필요가 없이 런타임시 리플랙션의 Proxy 클래스가 동적으로 생성해준다는 장점이 있다. 하지만, 문제가 발생하면 런타임 에러 가 발생하므로 컴파일 시 오류를 찾기가 어려운 문제점 또한 존재한다. 동적 프록시 기술을 사용하면 런타임시 프록시 객체 를 생성해준다. 리플렉션 을 이용해 프록시를 생성한다. 타겟 인터페이스와 동일한 형태로 생성 FactoryBean 을 통해서 생성 프록시 객체는 원본 객체의 대리자 역할을 하며, 클라이언트가 프록시 객체를 통해 원본 객체에 접근하면, 프록시 객체가 요청을 가로채서 필요한 전처리나 후처리를 수행한 후, 최종 결과를 반환합니다. 동적 프록시는 프로그래머가 직접 코드를 작성하지 않아도 인터페이스의 메서드 호출을 가로채서 처리할 수 있어서 매우 유용합니다. 예를 들어, AOP(Aspect Oriented Programming)에서는 동적 프록시를 이용해서 메서드 호출 전후에 로그를 남기거나, 보안 검사를 수행하거나, 트랜잭션 관리를 수행할 수 있습니다. JDK에서는 java.lang.reflect 패키지에서 Proxy 클래스 를 제공합니다. 이 클래스의 정적 메서드인 newProxyInstance() 메서드를 이용하면, 인터페이스와 InvocationHandler 인터페이스를 구현한 클래스를 전달하여 동적 프록시 객체를 생성할 수 있습니다. 이때, InvocationHandler 인터페이스를 구현한 클래스에서는 invoke() 메서드를 구현하여 원본 객체의 메서드 호출을 가로채서 필요한 작업을 수행하도록 구현합니다. newProxyInstance