public static <T> T getUltimateTargetObject(Object candidate) {
    Assert.notNull(candidate, "Candidate must not be null");
    try {
      if (AopUtils.isAopProxy(candidate) && (candidate instanceof Advised)) {
        Object target = ((Advised) candidate).getTargetSource().getTarget();
        if (target != null) {
          return (T) getUltimateTargetObject(target);
        }
      }
    }
    catch (Throwable ex) {
      throw new IllegalStateException("Failed to unwrap proxied object", ex);
    }
    return (T) candidate;
  }
public static < T > T getUltimateTargetObject ( Object candidate ) { Assert . notNull ( candidate , "Candidate must not be null" ) ; try { if ( AopUtils . isAopProxy ( candidate ) && ( candidate instanceof Advised ) ) { Object target = ( ( Advised ) candidate ) . getTargetSource ( ) . getTarget ( ) ; if ( target != null ) { return ( T ) getUltimateTargetObject ( target ) ; } } } catch ( Throwable ex ) { throw new IllegalStateException ( "Failed to unwrap proxied object" , ex ) ; } return ( T ) candidate ; }
Taken from {@link org.springframework.test.util.AopTestUtils#getUltimateTargetObject(java.lang.Object)}
and copied to provide support for versions earlier then Spring 4.2

Get the ultimate <em>target</em> object of the supplied {@code candidate}
object, unwrapping not only a top-level proxy but also any number of
nested proxies.
<p>If the supplied {@code candidate} is a Spring
{@linkplain AopUtils#isAopProxy proxy}, the ultimate target of all
nested proxies will be returned; otherwise, the {@code candidate}
will be returned <em>as is</em>.
@param candidate the instance to check (potentially a Spring AOP proxy;
never {@code null})
@return the target object or the {@code candidate} (never {@code null})
@throws IllegalStateException if an error occurs while unwrapping a proxy
@see Advised#getTargetSource()
@see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass