ByteBuddy를 살펴보자

https://www.baeldung.com/byte-buddy를 읽으며 내가 이해 하기 위해 번역한 문서입니다.

ByteBuddy란?

런타임 시에 java Class 들을 동적으로 만들어낼 수 있는 라이브러리 이다.

의존성추가

사용을 위해서 의존성을 추가하자

런타임 Java Class 생성

이미 존재하는 클래스의 서브클래스를 동적으로 생성해보자.
예를들어, Object.class의 toString() 메소드를 오버라이딩 한 서브클래스를 만들어보자.

ByteBuddy 인스턴스를 생성하였고. Object.class 상속을 위해 subclass() API를 사용했다.
또한 ElementMatchers를 이용하여 Object.class의 toString메소드를 선택했다.
마지막으로 intercept() API를 사용하여 toString() 메소드에서 고정값을 리턴하도록 하였다.
make() 메소드를 통해 새로운 클래스를 만든다.

이 시점에서, 우리의 클래스는 생성되었지만 JVM에 아직 로드되지 않은 상태이다. (이것은 DynamicType.Unloaded 의 인스턴스로 생성되며
생성한 타입의 binary form이다.)

그래서 아래와 같이 JVM에 생성된 클래스를 로드해야 한다.

아래와 같이 동적타입의 toString() 메소드 실행을 확인할수 있다.

메소드 위임과 커스텀 로직

앞선 예제에서 , 우리는 toString() 메소드에서 고정값을 리턴했다.

실제 업무 응용레벨에서는 이것보다 더 복잡한 로직을 요구한다.

커스텀 로직을 동적 타입으로 이용가능하게끔 하는 효과적인 방법은 메소드 호출 위임이다.

Foo.class 의 서브클래스를 동적 타입으로 만들어보자.
Foo.class는 sayHelloFoo() 메소드를 가지고있다.

또한 Bar라는 static sayHelloBar 메소드를 갖는 클래스를 만들어보자.

이제, ByteBuddy의 DSL을 사용하여 sayHelloFoo()의 모든 호출을 sayHelloBar()로 위임해보자.
이것은 우리에게 커스텀 로직 적용하는것을 허용해준다.

sayHelloFoo() 를 호출하면, sayHelloBar() 가 실행된다.

어떻게 ByteBuddy는 Bar.class 안의 어떤 메소드가 실행하기 위한 메소드인지 알수있을까?
그것은 메소드 signature와 리턴타입 메소드명, 어노테이션으로 매칭메소드에 의해 선택되어진다.

sahHelloFoo() 와 sayHelloBar 는 같은 이름을 갖지 않는다.
그러나 그들은 같은 메소드 signature와 리턴타입을 갖는다.

만약 Bar.class 내에 signature 와 리턴타입이 맞는 다수의 메소드가 있다면
@BindingPriority 어노테이션을 이용하여 애매모호함을 해결할 수 있다.

@BindingPriority 는 integer인자를 갖으며
높은 수로 구현체 호출의 우선순위를 갖는다.
그렇게,아래 코드 스니펫의 sayHelloBar() 는 sayBar() 보다도 우선되어질 것이다.

메소드와 필드 정의

동적타입의 슈퍼클래스 내 정의된 메소드를 재정의 할 수 있다.
동적타입 클래스에 새로운 메소드(또는 필드)를 추가하여 살펴보자.

동적 생성된 메소드 호출을 위해 java reflections을 사용할것이다.

Object.class 의 서브클래스로 MyClassName이라는 클래스를 만들었다.
그 다음 custom 이라는 이름으로 String 타입 리턴,public 접근 제한의 메소드를 만들었다.
앞선예제와 같이 , 호출을 가로채서 앞선 튜토리얼에서 만든 Bar.class 로 위임하는 메소드를 구현했다.

존재하는 클래스의 재정의

동적으로 생성 된 클래스로 작업했지만 이미 로드 된 클래스로도 작업 할 수 있다.
기존 클래스를 재정의 (또는 리베이스) 하고 ByteBuddyAgent를 이용하여 JVM으로 다시 로드 할 수 있다.

ByteBuddyAgent 의존성을 추가하자.

최신버전은 여기서 찾을 수 있다.

이제, 앞서 만든 Foo.class의 sayHelloFoo 메소드를 재정의 해보자.

ByteBuddy 라리브러리 기능과 이를 사용하여 동적 클래스를 효율적으로 만든는 방법을 살펴보았다.

이 문서는 라이브러리의 내부 동작 및 기타 측면에 대해 심층적인 설명을 제공합니다.

또한 튜토리얼 전체 코드 스니펫은 github에서 찾을 수 있습니다.

원본 문서

나의 생각

동적으로 바이트코드를 건드려서 클래스를 만들고 클래스로더에 올리고 하는 라이브러리 라고 생각.

다른 프레임워크 보다 성능은 더 좋은가?

오올

Written by

엘디는 사랑입니다.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store