Okay, think I've tracked it down. In Spring 3.0's TransactionSynchronizationUtils.unwrapResourceIfNe cessary() method
Code:
static Object unwrapResourceIfNecessary(Object resource) {
Assert.notNull(resource, "Resource must not be null");
Object resourceRef = resource;
// unwrap infrastructure proxy
if (resourceRef instanceof InfrastructureProxy) {
resourceRef = ((InfrastructureProxy) resourceRef).getWrappedObject();
}
if (aopAvailable) {
// now unwrap scoped proxy
resourceRef = ScopedProxyUnwrapper.unwrapIfNecessary(resource);
}
return resourceRef;
}
It's unwrapping the Proxy (InfrastructureProxy), but then if AOP is available, it calls ScopedProxyUnwrapper.unwrapIfNecessary(resource) on the original Proxy and because it's not a ScopedObject, it's overwriting the unwrapped object with the original proxy.
Edit: I see there is already a JIRA open for this: http://jira.springframework.org/browse/SPR-6625
Thank you.