27

I am trying to obtain some classes name by getClass().getSimpleName() under Spring and it returns something like

MyClass$$EnhancerBySpringCGLIB$$SOMEHEX

This is probably because Spring wraps the class into proxy.

Is there any portable way to obtain original class name?

Dims
  • 47,675
  • 117
  • 331
  • 600

2 Answers2

48

Spring provides a utility for this.

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/util/ClassUtils.html#getUserClass-java.lang.Class-

public static Class<?> getUserClass(Class<?> clazz)

"Return the user-defined class for the given class: usually simply the given class, but the original class in case of a CGLIB-generated subclass."

James Watkins
  • 4,806
  • 5
  • 32
  • 42
  • 1
    I forgot to mention: this only works for objects proxied by spring. There is no general solution for detecting the target type of any given proxy. The way I solve this is by explicitly defining the target type of my proxies external to the proxy itself. – James Watkins Dec 21 '17 at 15:50
  • Thank you! This worked while other suggestions such as `TargetAwareClass` failed on class cast exception. – Don Rhummy Mar 14 '19 at 00:51
  • 5
    In spring boot: `log.debug(ClassUtils.getUserClass(constraintDescriptor.getAnnotation()).getName());` is `com.sun.proxy.$Proxy153` :-/ – e-info128 Aug 11 '20 at 07:23
  • How it works when Spring creates the proxy class using JDK dynamic proxies mechanism instead of cglib? – amseager Oct 01 '20 at 07:49
  • @e-info128 : did you find a solution ? – serv-inc Dec 22 '21 at 14:18
3

I'd had a similar problem like yours. I'd wanted to write log my repository name at a method of AOP. When I tried with ClassUtils.getUserClass() from upper James' answer, my aop method write log as same as before.

I solved the problem with AopProxyUtils.getSingletonTarget().

Plus, I leave following cases for someone who will have same problem.

@SpringBootTest
class AopLoggingServiceTest {

    @Autowired
    TestRepository testRepository;

    public void someAopMethod(){
        Class<?> try1 = AopUtils.getTargetClass(testRepository);
        System.out.println("AopUtils.getTargetClass : " + try1);
        Class<?> try2 = ClassUtils.getUserClass(testRepository);
        System.out.println("ClassUtils.getUserClass : " + try2);
        Class<?> try3 = AopProxyUtils.ultimateTargetClass(testRepository);
        System.out.println("AopProxyUtils.ultimateTargetClass : " + try3);
        Class<?> finalTry = AopProxyUtils.proxiedUserInterfaces(testRepository)[0];
        System.out.println ("AopProxyUtils.proxiedUserInterfaces[0] : " + finalTry);
    }
}

outputs :

AopUtils.getTargetClass : class com.sun.proxy.$Proxy172
AopProxyUtils.ultimateTargetClass : class org.springframework.data.jpa.repository.support.SimpleJpaRepository
ClassUtils.getUserClass : class com.sun.proxy.$Proxy172
AopProxyUtils.proxiedUserInterfaces[0] : interface io.juyeon.test.repository.TestRepository
Vladislav Varslavans
  • 2,775
  • 4
  • 18
  • 33
Juyeon
  • 403
  • 4
  • 8