Check for advisor-introduced interfaces specifically
See gh-31304
This commit is contained in:
parent
d3dd01e227
commit
8680c43368
|
@ -34,6 +34,7 @@ import org.springframework.aop.IntroductionAdvisor;
|
|||
import org.springframework.aop.IntroductionInfo;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.aop.SpringProxy;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.support.DefaultIntroductionAdvisor;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
|
@ -222,15 +223,15 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
|||
|
||||
/**
|
||||
* Add a new proxied interface.
|
||||
* @param intf the additional interface to proxy
|
||||
* @param ifc the additional interface to proxy
|
||||
*/
|
||||
public void addInterface(Class<?> intf) {
|
||||
Assert.notNull(intf, "Interface must not be null");
|
||||
if (!intf.isInterface()) {
|
||||
throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
|
||||
public void addInterface(Class<?> ifc) {
|
||||
Assert.notNull(ifc, "Interface must not be null");
|
||||
if (!ifc.isInterface()) {
|
||||
throw new IllegalArgumentException("[" + ifc.getName() + "] is not an interface");
|
||||
}
|
||||
if (!this.interfaces.contains(intf)) {
|
||||
this.interfaces.add(intf);
|
||||
if (!this.interfaces.contains(ifc)) {
|
||||
this.interfaces.add(ifc);
|
||||
adviceChanged();
|
||||
}
|
||||
}
|
||||
|
@ -238,12 +239,12 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
|||
/**
|
||||
* Remove a proxied interface.
|
||||
* <p>Does nothing if the given interface isn't proxied.
|
||||
* @param intf the interface to remove from the proxy
|
||||
* @param ifc the interface to remove from the proxy
|
||||
* @return {@code true} if the interface was removed; {@code false}
|
||||
* if the interface was not found and hence could not be removed
|
||||
*/
|
||||
public boolean removeInterface(Class<?> intf) {
|
||||
return this.interfaces.remove(intf);
|
||||
public boolean removeInterface(Class<?> ifc) {
|
||||
return this.interfaces.remove(ifc);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -252,15 +253,37 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isInterfaceProxied(Class<?> intf) {
|
||||
public boolean isInterfaceProxied(Class<?> ifc) {
|
||||
for (Class<?> proxyIntf : this.interfaces) {
|
||||
if (intf.isAssignableFrom(proxyIntf)) {
|
||||
if (ifc.isAssignableFrom(proxyIntf)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean hasUserSuppliedInterfaces() {
|
||||
for (Class<?> ifc : this.interfaces) {
|
||||
if (!SpringProxy.class.isAssignableFrom(ifc) && !isAdvisorIntroducedInterface(ifc)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isAdvisorIntroducedInterface(Class<?> ifc) {
|
||||
for (Advisor advisor : this.advisors) {
|
||||
if (advisor instanceof IntroductionAdvisor introductionAdvisor) {
|
||||
for (Class<?> introducedInterface : introductionAdvisor.getInterfaces()) {
|
||||
if (introducedInterface == ifc) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Advisor[] getAdvisors() {
|
||||
|
|
|
@ -19,7 +19,6 @@ package org.springframework.aop.framework;
|
|||
import java.io.Serializable;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.springframework.aop.SpringProxy;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
|
@ -59,7 +58,7 @@ public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
|
|||
|
||||
@Override
|
||||
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
|
||||
if (config.isOptimize() || config.isProxyTargetClass() || !hasTargetInterfaces(config)) {
|
||||
if (config.isOptimize() || config.isProxyTargetClass() || !config.hasUserSuppliedInterfaces()) {
|
||||
Class<?> targetClass = config.getTargetClass();
|
||||
if (targetClass == null) {
|
||||
throw new AopConfigException("TargetSource cannot determine target class: " +
|
||||
|
@ -75,14 +74,4 @@ public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean hasTargetInterfaces(AdvisedSupport config) {
|
||||
Class<?> targetClass = config.getTargetClass();
|
||||
for (Class<?> ifc : config.getProxiedInterfaces()) {
|
||||
if (targetClass != null ? ifc.isAssignableFrom(targetClass) : !SpringProxy.class.isAssignableFrom(ifc)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ class ProxyFactoryTests {
|
|||
Class<?>[] oldProxiedInterfaces = pf.getProxiedInterfaces();
|
||||
long t = 555555L;
|
||||
TimestampIntroductionInterceptor ti = new TimestampIntroductionInterceptor(t);
|
||||
pf.addAdvisor(0, new DefaultIntroductionAdvisor(ti, TimeStamped.class));
|
||||
pf.addAdvisor(new DefaultIntroductionAdvisor(ti, TimeStamped.class));
|
||||
|
||||
Class<?>[] newProxiedInterfaces = pf.getProxiedInterfaces();
|
||||
assertThat(newProxiedInterfaces).as("Advisor proxies one more interface after introduction").hasSize(oldProxiedInterfaces.length + 1);
|
||||
|
@ -328,11 +328,11 @@ class ProxyFactoryTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void proxyTargetClassWithIntroducedInterface() {
|
||||
void proxyTargetClassInCaseOfIntroducedInterface() {
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.setTargetClass(MyDate.class);
|
||||
TimestampIntroductionInterceptor ti = new TimestampIntroductionInterceptor(0L);
|
||||
pf.addAdvisor(0, new DefaultIntroductionAdvisor(ti, TimeStamped.class));
|
||||
pf.addAdvisor(new DefaultIntroductionAdvisor(ti, TimeStamped.class));
|
||||
Object proxy = pf.getProxy();
|
||||
assertThat(AopUtils.isCglibProxy(proxy)).as("Proxy is a CGLIB proxy").isTrue();
|
||||
assertThat(proxy).isInstanceOf(MyDate.class);
|
||||
|
@ -340,6 +340,20 @@ class ProxyFactoryTests {
|
|||
assertThat(AopProxyUtils.ultimateTargetClass(proxy)).isEqualTo(MyDate.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void proxyInterfaceInCaseOfNonTargetInterface() {
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
pf.setTargetClass(MyDate.class);
|
||||
pf.addInterface(TimeStamped.class);
|
||||
pf.addAdvice((MethodInterceptor) invocation -> {
|
||||
throw new UnsupportedOperationException();
|
||||
});
|
||||
Object proxy = pf.getProxy();
|
||||
assertThat(AopUtils.isJdkDynamicProxy(proxy)).as("Proxy is a JDK proxy").isTrue();
|
||||
assertThat(proxy).isInstanceOf(TimeStamped.class);
|
||||
assertThat(AopProxyUtils.ultimateTargetClass(proxy)).isEqualTo(MyDate.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void interfaceProxiesCanBeOrderedThroughAnnotations() {
|
||||
Object proxy1 = new ProxyFactory(new A()).getProxy();
|
||||
|
|
Loading…
Reference in New Issue