Make proxyTargetClass=true with introduction advice work for JDK proxy targets
Closes gh-27044
This commit is contained in:
parent
74f91339e2
commit
c45c46dad7
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.aop.framework.autoproxy;
|
package org.springframework.aop.framework.autoproxy;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -440,7 +441,17 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||||
ProxyFactory proxyFactory = new ProxyFactory();
|
ProxyFactory proxyFactory = new ProxyFactory();
|
||||||
proxyFactory.copyFrom(this);
|
proxyFactory.copyFrom(this);
|
||||||
|
|
||||||
if (!proxyFactory.isProxyTargetClass()) {
|
if (proxyFactory.isProxyTargetClass()) {
|
||||||
|
// Explicit handling of JDK proxy targets (for introduction advice scenarios)
|
||||||
|
if (Proxy.isProxyClass(beanClass)) {
|
||||||
|
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
|
||||||
|
for (Class<?> ifc : beanClass.getInterfaces()) {
|
||||||
|
proxyFactory.addInterface(ifc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// No proxyTargetClass flag enforced, let's apply our default checks...
|
||||||
if (shouldProxyTargetClass(beanClass, beanName)) {
|
if (shouldProxyTargetClass(beanClass, beanName)) {
|
||||||
proxyFactory.setProxyTargetClass(true);
|
proxyFactory.setProxyTargetClass(true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2021 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.
|
||||||
|
|
@ -28,6 +28,7 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.aop.TargetSource;
|
import org.springframework.aop.TargetSource;
|
||||||
import org.springframework.aop.framework.ProxyFactory;
|
import org.springframework.aop.framework.ProxyFactory;
|
||||||
import org.springframework.aop.support.AopUtils;
|
import org.springframework.aop.support.AopUtils;
|
||||||
|
import org.springframework.aop.support.DefaultIntroductionAdvisor;
|
||||||
import org.springframework.aop.target.SingletonTargetSource;
|
import org.springframework.aop.target.SingletonTargetSource;
|
||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
|
@ -219,7 +220,7 @@ public class AutoProxyCreatorTests {
|
||||||
|
|
||||||
MutablePropertyValues pvs = new MutablePropertyValues();
|
MutablePropertyValues pvs = new MutablePropertyValues();
|
||||||
pvs.add("proxyFactoryBean", "false");
|
pvs.add("proxyFactoryBean", "false");
|
||||||
sac.registerSingleton("testAutoProxyCreator", TestAutoProxyCreator.class, pvs);
|
sac.registerSingleton("testAutoProxyCreator", IntroductionTestAutoProxyCreator.class, pvs);
|
||||||
|
|
||||||
sac.registerSingleton("noInterfaces", NoInterfaces.class);
|
sac.registerSingleton("noInterfaces", NoInterfaces.class);
|
||||||
sac.registerSingleton("containerCallbackInterfacesOnly", ContainerCallbackInterfacesOnly.class);
|
sac.registerSingleton("containerCallbackInterfacesOnly", ContainerCallbackInterfacesOnly.class);
|
||||||
|
|
@ -248,9 +249,9 @@ public class AutoProxyCreatorTests {
|
||||||
singletonNoInterceptor.getName();
|
singletonNoInterceptor.getName();
|
||||||
assertThat(tapc.testInterceptor.nrOfInvocations).isEqualTo(0);
|
assertThat(tapc.testInterceptor.nrOfInvocations).isEqualTo(0);
|
||||||
singletonToBeProxied.getAge();
|
singletonToBeProxied.getAge();
|
||||||
assertThat(tapc.testInterceptor.nrOfInvocations).isEqualTo(1);
|
|
||||||
prototypeToBeProxied.getSpouse();
|
|
||||||
assertThat(tapc.testInterceptor.nrOfInvocations).isEqualTo(2);
|
assertThat(tapc.testInterceptor.nrOfInvocations).isEqualTo(2);
|
||||||
|
prototypeToBeProxied.getSpouse();
|
||||||
|
assertThat(tapc.testInterceptor.nrOfInvocations).isEqualTo(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -404,7 +405,7 @@ public class AutoProxyCreatorTests {
|
||||||
else if (name.endsWith("ToBeProxied")) {
|
else if (name.endsWith("ToBeProxied")) {
|
||||||
boolean isFactoryBean = FactoryBean.class.isAssignableFrom(beanClass);
|
boolean isFactoryBean = FactoryBean.class.isAssignableFrom(beanClass);
|
||||||
if ((this.proxyFactoryBean && isFactoryBean) || (this.proxyObject && !isFactoryBean)) {
|
if ((this.proxyFactoryBean && isFactoryBean) || (this.proxyObject && !isFactoryBean)) {
|
||||||
return new Object[] {this.testInterceptor};
|
return getAdvicesAndAdvisors();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return DO_NOT_PROXY;
|
return DO_NOT_PROXY;
|
||||||
|
|
@ -414,6 +415,10 @@ public class AutoProxyCreatorTests {
|
||||||
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
|
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Object[] getAdvicesAndAdvisors() {
|
||||||
|
return new Object[] {this.testInterceptor};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -426,6 +431,17 @@ public class AutoProxyCreatorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public static class IntroductionTestAutoProxyCreator extends TestAutoProxyCreator {
|
||||||
|
|
||||||
|
protected Object[] getAdvicesAndAdvisors() {
|
||||||
|
DefaultIntroductionAdvisor advisor = new DefaultIntroductionAdvisor(this.testInterceptor);
|
||||||
|
advisor.addInterface(Serializable.class);
|
||||||
|
return new Object[] {this.testInterceptor, advisor};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interceptor that counts the number of non-finalize method calls.
|
* Interceptor that counts the number of non-finalize method calls.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue