[java] Java Byte Buddy를 사용한 싱글톤 패턴

싱글톤 패턴은 자바 애플리케이션에서 인스턴스가 하나만 생성되도록 보장하는 디자인 패턴입니다. 일반적으로 private 생성자, 정적인스턴스 변수 및 정적 메서드를 사용하여 구현됩니다. 그러나 이런 방식은 boilerplate code(상용구 코드)가 필요하고 유지보수가 어렵다는 단점이 있습니다.

Java Byte Buddy는 바이트 코드 조작 라이브러리로서 동적으로 클래스를 만들거나 수정하는 데 사용할 수 있습니다. 이를 사용하면 싱글톤 패턴을 직접 구현하는 번거로움 없이 간단하고 효율적으로 생성할 수 있습니다.

Byte Buddy 라이브러리 추가

Maven 또는 Gradle을 사용하는 경우, 프로젝트 의존성에 다음 라이브러리를 추가합니다.

Maven:

<dependency>
    <groupId>net.bytebuddy</groupId>
    <artifactId>byte-buddy</artifactId>
    <version>1.11.0</version>
</dependency>

Gradle:

compile 'net.bytebuddy:byte-buddy:1.11.0'

싱글톤 클래스 생성

다음은 Byte Buddy를 사용하여 싱글톤 클래스를 동적으로 생성하는 예제입니다.

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.matcher.ElementMatchers;

public class SingletonGenerator {

    public static <T> T createSingleton(Class<T> clazz) throws IllegalAccessException, InstantiationException {
        return new ByteBuddy()
                .subclass(clazz)
                .method(ElementMatchers.isDefaultMethod().or(ElementMatchers.isAbstract()))
                .intercept(MethodDelegation.to(SingletonInterceptor.class))
                .make()
                .load(clazz.getClassLoader())
                .getLoaded()
                .newInstance();
    }

    public static class SingletonInterceptor {

        private static volatile Object instance;

        public static Object intercept() throws Exception {
            if (instance == null) {
                synchronized (SingletonInterceptor.class) {
                    if (instance == null) {
                        instance = SuperMethodCall.INSTANCE.invoke();
                    }
                }
            }
            return instance;
        }
    }
}

위의 예제에서는 createSingleton() 메서드를 사용하여 주어진 클래스를 싱글톤으로 생성합니다. ByteBuddy 객체를 사용하여 주어진 클래스를 서브클래스화하고, MethodDelegation을 통해 SingletonInterceptor 클래스의 인터셉터를 적용합니다. 인터셉터에서는 실제 인스턴스 생성 및 반환을 관리하고, 더블 체크 락킹(Double-Checked Locking)으로 스레드 안전성을 보장합니다.

사용 예제

다음은 위에서 생성한 싱글톤 생성기를 사용하는 예제입니다.

public class SingletonExample {

    public static void main(String[] args) {
        MySingleton singleton = SingletonGenerator.createSingleton(MySingleton.class);

        singleton.sayHello();
    }

    public static class MySingleton {

        private MySingleton() {
            System.out.println("Creating MySingleton instance");
        }

        public void sayHello() {
            System.out.println("Hello, World!");
        }
    }
}

위의 예제에서는 createSingleton() 메서드를 사용하여 MySingleton 클래스의 싱글톤 인스턴스를 생성하고, sayHello() 메서드를 호출합니다. MySingleton 클래스는 생성자가 호출되는 시점에 메시지를 출력하도록 구현되어 있습니다.

결론

Java Byte Buddy를 사용하여 싱글톤 패턴을 동적으로 생성할 수 있습니다. 이를 통해 boilerplate code 없이 싱글톤을 생성하고 유지할 수 있습니다. Byte Buddy의 강력한 기능과 유연성을 통해 자바 애플리케이션의 디자인 패턴 구현을 간소화할 수 있습니다.


참고 문서: