diff --git a/spring-core/aop/src/test/java/com/example/aop/proxyvs/ProxyCastingTest.java b/spring-core/aop/src/test/java/com/example/aop/proxyvs/ProxyCastingTest.java new file mode 100644 index 00000000..cf366f9d --- /dev/null +++ b/spring-core/aop/src/test/java/com/example/aop/proxyvs/ProxyCastingTest.java @@ -0,0 +1,42 @@ +package com.example.aop.proxyvs; + +import com.example.aop.member.MemberService; +import com.example.aop.member.MemberServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.aop.framework.ProxyFactory; + +import static org.junit.jupiter.api.Assertions.*; + +@Slf4j +public class ProxyCastingTest { + + @Test + void jdkProxy() { + MemberServiceImpl target = new MemberServiceImpl(); + ProxyFactory proxyFactory = new ProxyFactory(target); + proxyFactory.setProxyTargetClass(false); // JDK 동적 프록시 (인터페이스 기반) + + // 프록시를 인터페이스로 캐스팅 가능 + MemberService memberServiceProxy = (MemberService) proxyFactory.getProxy(); + + // JDK 동적 프록시를 구현 클래스로 캐스팅 불가능, ClassCastException 예외 발생 + assertThrows(ClassCastException.class, () -> { + MemberServiceImpl casingMemberService = (MemberServiceImpl) memberServiceProxy; + }); + } + + @Test + void cglibProxy() { + MemberServiceImpl target = new MemberServiceImpl(); + ProxyFactory proxyFactory = new ProxyFactory(target); + proxyFactory.setProxyTargetClass(true); // CGLIB 프록시 (구현체 기반) + + // 프록시를 인터페이스로 캐스팅 가능 + MemberService memberServiceProxy = (MemberService) proxyFactory.getProxy(); + + // CGLIB 프록시를 구현 클래스로 캐스팅 가능 + MemberServiceImpl casingMemberService = (MemberServiceImpl) memberServiceProxy; + } +} diff --git a/spring-core/aop/src/test/java/com/example/aop/proxyvs/ProxyDITest.java b/spring-core/aop/src/test/java/com/example/aop/proxyvs/ProxyDITest.java new file mode 100644 index 00000000..e6787aaf --- /dev/null +++ b/spring-core/aop/src/test/java/com/example/aop/proxyvs/ProxyDITest.java @@ -0,0 +1,34 @@ +package com.example.aop.proxyvs; + +import com.example.aop.member.MemberService; +import com.example.aop.member.MemberServiceImpl; +import com.example.aop.proxyvs.code.ProxyDIAspect; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; + +@Slf4j +//@SpringBootTest(properties = {"spring.aop.proxy-target-class=false"}) // JDK 동적 프록시 +//@SpringBootTest(properties = {"spring.aop.proxy-target-class=true"}) // CGLIB 프록시 +@SpringBootTest +@Import(ProxyDIAspect.class) +public class ProxyDITest { + + @Autowired + MemberService memberService; + + /** + * JDK 동적 프록시 생성 시 타입 캐스트 불가능 (인터페이스 기반이므로 구체클래스를 알 수 없다.) + */ + @Autowired + MemberServiceImpl memberServiceImpl; + + @Test + void go() { + log.info("memberService class={}", memberService.getClass()); + log.info("memberServiceImpl class={}", memberServiceImpl.getClass()); + memberService.hello("hello"); + } +} diff --git a/spring-core/aop/src/test/java/com/example/aop/proxyvs/code/ProxyDIAspect.java b/spring-core/aop/src/test/java/com/example/aop/proxyvs/code/ProxyDIAspect.java new file mode 100644 index 00000000..c907aed3 --- /dev/null +++ b/spring-core/aop/src/test/java/com/example/aop/proxyvs/code/ProxyDIAspect.java @@ -0,0 +1,16 @@ +package com.example.aop.proxyvs.code; + +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; + +@Slf4j +@Aspect +public class ProxyDIAspect { + + @Before("execution(* com.example.aop..*.*(..))") + public void doTrace(JoinPoint joinPoint) { + log.info("[proxyDIAdvice] {}", joinPoint.getSignature()); + } +}