Java에서는 InvocationHandler
구현을 사용하여 동적 프록시를 만들 수 있습니다. JVM 최적화에도 불구하고 리플렉션을 사용하면 항상 메소드를 호출하는 오버 헤드가 발생합니다.ByteBuddy를 사용하여 동적 프록시를 만드는 방법
이 문제를 해결하기 위해 런타임시 프록시 클래스를 만들기 위해 ByteBuddy를 사용하려고했지만 문서가이 부분에서 충분히 명확하지 않은 것 같습니다.
메소드 호출을 일부 클래스 인스턴스로 전달하기 위해 MethodCallProxy
을 어떻게 만듭니 까?
편집 : 내가 RPC 시스템을 구축하고
:
더 나은 내 문제를 명확히하기 위해, 나는 내가 무엇을 달성하고자하는의 예를 제공하고 있습니다. 메소드 호출의 각면에서, 나는 (두 호출자/피 호출자가 JVM 하에서 실행될 때) 계약을 정의하는 인터페이스를 가지고있다.
@Contract
interface ISomeService {
fun someMethod(arg0: String, arg1: SomePojo): PojoResult
}
호출 사이트에서 모든 메소드 호출을 가로 채어 호출 수신자에게 전달하는 프록시를 주입합니다.
ByteBuddy()
.subclass(Any::class.java)
.implement(serviceClass)
// Service contract method delegation
.method(isDeclaredBy(serviceClass)).intercept(
MethodDelegation
.to(ServiceProxyInterceptor())
.filter(not(isDeclaredBy(Any::class.java)))
)
.make()
.load(this)
.loaded as Class<T>
는 그리고, 마지막으로, 호출자에서, 나는 호출 매개 변수를 비 정렬 화 및 서비스 구현에 전달에 대한 책임 여러 핸들러, 각 서비스 방법 하나를 가지고있다.
@Service
class SomeServiceImpl {
fun someMethod(arg0: String, arg1: SomePojo): PojoResult {
// ...
}
}
나는 코드 생성을 사용하여이 문제를 해결할 수 있지만 결과 jar
파일이 매우 큰이 될 수 있습니다. 따라서이 핸들러의 제네릭 버전을 만들고 각각의 인스턴스에서 모든 메서드 호출을 가로 채어 ISomeService
에 가로 채고 SomeServiceImpl
에 전달하는 프록시를 연결하려고합니다.
물론이 질문의 특정 부분을 다루기 위해, ByteBuddy가 생성 한 프록시가 InvokeHandler를 호출하는 것이 JRE가'java.lang.reflect.Proxy'를 호출하는 데 더 효율적이라고 가정 할 이유가 없습니다. InvocationHandler' ... – Holger
차이점은 대부분 JVM이 인터페이스 만 지원하는 반면 Byte Buddy는 클래스를 계측 할 수 있다는 것입니다. 필자는 성능면에서 코드 생성의 이점을 리플렉션에 비해 나타냈다 고 생각합니다. 그러나 후자는 의심 스럽다. 대부분의 경우, 반사 반등이 충분하다는 것을 알 수 있습니다. –
ByteBuddy와 Reflection의 차이점을 알고 있지만, 문제가 전혀 문제가되지 않는다는 것을 알 수 있습니다. 언급 된 유일한 동기는 Reflection의 청구 된 오버 헤드입니다. 성능 문제가있는 시나리오가있을 수 있지만'InvocationHandler'를 고수하면 코드 생성이 잘못된 끝을 처리합니다. 예를 들어 기본 유형의 복싱과 인수를 배열에 채우는 것이 계속 발생합니다. – Holger