Open her0807 opened 1 year ago
프록시의 사용 목적
핵심 기능 코드
에 부가기능 구현 코드
를 덮은 것
타깃에 부가기능을 런타임시 다이나믹하게 부여해주기 위해서 프록시를 사용하는 패턴을 말한다.
여러개의 프록시를 사용할 수 있다.
프록시는 기존 코드에 영향을 주지 않으면서 타깃의 기능을 확장하거나 접근 방법을 제어할 수 있는 유용한 방법이다.
Q. Spring AOP는 프록시 기반으로 JDK Dynamic Proxy와 CGLIB을 활용하여 AOP 제공한다 왜 두개를 제공할까?
우선 프록시를 제공 받기 위해서는 인터페이스가 존재해야한다. 이게 다이나믹 동적 프록시에 기본인데, 매번 인터페이스를 만들고 모든 코드를 구현하는것은 상당한 비용이다.
그래서 리플렉션을 사용해 런타임 위빙시 클래스 정보를 가져와 바이트 코드를 조작하는 cglib 방식도 있다. 이 방법은 Spring AOP 적용시 하나만 사용되는게 아니라 인터페이스가 있는지 유무를 판단하여 내부 로직에서 혼용해서 사용되고 있다.
jdk Dynamic 동적 프록시
는
코드의 복잡도가 증가
인터페이스 구현, 프록시 객체 생성 등등 복잡하다
CGLIB Proxy
메서드에 final을 붙이면 오버라이딩이 불가능
net.sf.cglib.proxy.Enhancer 의존성을 추가해야한다
Default 생성자 필요
없는 경우 예외 발생
구현을 가져갈 것인지, 성능을 가져갈 것인지 고민이 필요
@@ 참고자료 https://gmoon92.github.io/spring/aop/2019/04/20/jdk-dynamic-proxy-and-cglib.html
스프링의 빈은 기본적으로 클래스 이름과 프로퍼티로 정의된다. 다이나믹 프록시는 지정된 클래스 이름을 가지고 리플렉션을 사용하여 빈 오브젝트를 만든다.
클래스 이름이 달라지면 -> 빈 등록된 내역을 찾을 수 없음. 동적 프록시기 때문에 런타임 시점에 빈을 추가할 방법은 없음.
그래서 기존 틀(껍데기를) 만들고 해당 껍데기 내부에 구현체를 리플랙션으로 정의하는 거임
Proxy.newProxyInstance 메서드는 자바에서 동적 프록시를 생성하는 편리하고 타입 안전하며 표준화된 방법입니다. 이 메서드는 프록시 생성의 복잡성을 추상화하고 InvocationHandler를 통해 프록시 동작을 정의하는 데 개발자가 집중할 수 있도록 합니다. 이 팩토리 메서드를 사용하지 않고 수동으로 동적 프록시를 생성할 수는 있지만, 대부분의 사용 사례에 대해 추상화가 필요한 낮은 수준의 세부 사항을 처리해야 합니다.
이 방법은 직접 타깃 오브젝트를 뜯어 고쳐서 부가기능을 넣어주는 방법을 사용한다.
소스 코드를 직접 수정할 수는 없으니 클래스가 jvm 에 로딩되는 시점(컴파일 시점 )을 가로채서 바이트 코드를 조작하는 복잡한 방식을 사용한다.
해당 방식의 장점은
required
: 기존 트랜잭션에 참여한다.
required new
: 새로운 트랜잭션을 연다.
not supported
: 트랜잭션을 사용하지 않는다.
공통로직을 추출해서 한곳에서 관리하고 원하는 시점에 기존 비지니스 로직 위, 아래로 붙일 수 있는 기술이다