Spring에서 프록시 객체는 AOP, @Transactional, @Cacheable 등 다양한 기능을 구현하기 위해 사용된다. 이러한 프록시 객체는 원본 클래스의 어노테이션 정보를 직접적으로 가져올 수 없는 제약이 있다.

이 문제를 해결하기 위해 프록시 객체에서 원본 객체를 찾아내는 여러 가지 방법이 존재한다.

1.

Spring AOP에서 제공하는 유틸리티를 사용하여 프록시의 실제 타겟 클래스를 얻을 수 있다.

val targetClass = AopProxyUtils.ultimateTargetClass(proxyService)

2.

프록시 객체가 구현하는 Advised 인터페이스를 통해 실제 타겟 객체를 직접 참조할 수 있다.

val targetObject = getTargetObject(proxyService)

fun getTargetObject(proxy: Any): Any? {
    return if (AopUtils.isAopProxy(proxy) && proxy is Advised) {
        proxy.targetSource.target
    } else {
        proxy
    }
}

3.

CGLIB를 사용한 프록시의 경우, 원본 클래스는 프록시 클래스의 슈퍼클래스이다. 클래스 이름에 “CGLIB”가 포함되어 있는지 확인하여 원본 클래스를 찾을 수 있다.

val originalClass = getOriginalClass(proxyService)

fun getOriginalClass(obj: Any): Class<*> {
    return if (obj::class.java.name.contains("CGLIB")) {
        obj::class.java.superclass
    } else {
        obj::class.java
    }
}