introduced AopProxyUtils.ultimateTargetClass (SPR-7074)

This commit is contained in:
Juergen Hoeller 2010-04-22 21:36:53 +00:00
parent b28310b051
commit 87e327773e
3 changed files with 50 additions and 6 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,6 +19,9 @@ package org.springframework.aop.framework;
import java.util.Arrays; import java.util.Arrays;
import org.springframework.aop.SpringProxy; import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;
import org.springframework.aop.TargetSource;
import org.springframework.aop.target.SingletonTargetSource;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -34,6 +37,34 @@ import org.springframework.util.Assert;
*/ */
public abstract class AopProxyUtils { public abstract class AopProxyUtils {
/**
* Determine the ultimate target class of the given bean instance, traversing
* not only a top-level proxy but any number of nested proxies as well -
* as long as possible without side effects, that is, just for singleton targets.
* @param candidate the instance to check (might be an AOP proxy)
* @return the target class (or the plain class of the given object as fallback;
* never <code>null</code>)
* @see org.springframework.aop.TargetClassAware#getTargetClass()
* @see org.springframework.aop.framework.Advised#getTargetSource()
*/
public static Class<?> ultimateTargetClass(Object candidate) {
Assert.notNull(candidate, "Candidate object must not be null");
Object current = candidate;
Class<?> result = null;
while (current instanceof TargetClassAware) {
result = ((TargetClassAware) current).getTargetClass();
Object nested = null;
if (current instanceof Advised) {
TargetSource targetSource = ((Advised) current).getTargetSource();
if (targetSource instanceof SingletonTargetSource) {
nested = ((SingletonTargetSource) targetSource).getTarget();
}
}
current = nested;
}
return result;
}
/** /**
* Determine the complete set of interfaces to proxy for the given AOP configuration. * Determine the complete set of interfaces to proxy for the given AOP configuration.
* <p>This will always add the {@link Advised} interface unless the AdvisedSupport's * <p>This will always add the {@link Advised} interface unless the AdvisedSupport's

View File

@ -98,13 +98,13 @@ public abstract class AopUtils {
} }
/** /**
* Determine the target class of the given bean instance, * Determine the target class of the given bean instance which might be an AOP proxy.
* which might be an AOP proxy.
* <p>Returns the target class for an AOP proxy and the plain class else. * <p>Returns the target class for an AOP proxy and the plain class else.
* @param candidate the instance to check (might be an AOP proxy) * @param candidate the instance to check (might be an AOP proxy)
* @return the target class (or the plain class of the given object as fallback; * @return the target class (or the plain class of the given object as fallback;
* never <code>null</code>) * never <code>null</code>)
* @see org.springframework.aop.TargetClassAware#getTargetClass() * @see org.springframework.aop.TargetClassAware#getTargetClass()
* @see org.springframework.aop.framework.AopProxyUtils#ultimateTargetClass(Object)
*/ */
public static Class<?> getTargetClass(Object candidate) { public static Class<?> getTargetClass(Object candidate) {
Assert.notNull(candidate, "Candidate object must not be null"); Assert.notNull(candidate, "Candidate object must not be null");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -293,20 +293,33 @@ public final class ProxyFactoryTests {
public void testProxyTargetClassWithInterfaceAsTarget() { public void testProxyTargetClassWithInterfaceAsTarget() {
ProxyFactory pf = new ProxyFactory(); ProxyFactory pf = new ProxyFactory();
pf.setTargetClass(ITestBean.class); pf.setTargetClass(ITestBean.class);
Object proxy = pf.getProxy(); Object proxy = pf.getProxy();
assertTrue("Proxy is a JDK proxy", AopUtils.isJdkDynamicProxy(proxy)); assertTrue("Proxy is a JDK proxy", AopUtils.isJdkDynamicProxy(proxy));
assertTrue(proxy instanceof ITestBean); assertTrue(proxy instanceof ITestBean);
assertEquals(ITestBean.class, AopProxyUtils.ultimateTargetClass(proxy));
ProxyFactory pf2 = new ProxyFactory(proxy);
Object proxy2 = pf2.getProxy();
assertTrue("Proxy is a JDK proxy", AopUtils.isJdkDynamicProxy(proxy2));
assertTrue(proxy2 instanceof ITestBean);
assertEquals(ITestBean.class, AopProxyUtils.ultimateTargetClass(proxy2));
} }
@Test @Test
public void testProxyTargetClassWithConcreteClassAsTarget() { public void testProxyTargetClassWithConcreteClassAsTarget() {
ProxyFactory pf = new ProxyFactory(); ProxyFactory pf = new ProxyFactory();
pf.setTargetClass(TestBean.class); pf.setTargetClass(TestBean.class);
Object proxy = pf.getProxy(); Object proxy = pf.getProxy();
assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy)); assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy));
assertTrue(proxy instanceof TestBean); assertTrue(proxy instanceof TestBean);
assertEquals(TestBean.class, AopProxyUtils.ultimateTargetClass(proxy));
ProxyFactory pf2 = new ProxyFactory(proxy);
pf2.setProxyTargetClass(true);
Object proxy2 = pf2.getProxy();
assertTrue("Proxy is a CGLIB proxy", AopUtils.isCglibProxy(proxy2));
assertTrue(proxy2 instanceof TestBean);
assertEquals(TestBean.class, AopProxyUtils.ultimateTargetClass(proxy2));
} }
@Test @Test