Allow AOP proxies to be created using the original ClassLoader

Closes gh-26601
This commit is contained in:
Juergen Hoeller 2021-02-25 17:48:01 +01:00
parent 8baf404893
commit e53cce0778
2 changed files with 29 additions and 2 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -46,6 +46,7 @@ import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.core.SmartClassLoader;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -458,7 +459,11 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
ClassLoader targetClassLoader = getProxyClassLoader();
if (targetClassLoader instanceof SmartClassLoader && targetClassLoader != beanClass.getClassLoader()) {
targetClassLoader = ((SmartClassLoader) targetClassLoader).getOriginalClassLoader();
}
return proxyFactory.getProxy(targetClassLoader);
}
/**

View File

@ -47,6 +47,28 @@ public interface SmartClassLoader {
return false;
}
/**
* Return the original ClassLoader for this SmartClassLoader, or potentially
* the present loader itself if it is self-sufficient.
* <p>The default implementation returns the local ClassLoader reference as-is.
* In case of a reloadable or other selectively overriding ClassLoader which
* commonly deals with unaffected classes from a base application class loader,
* this should get implemented to return the original ClassLoader that the
* present loader got derived from (e.g. through {@code return getParent();}).
* <p>This gets specifically used in Spring's AOP framework to determine the
* class loader for a specific proxy in case the target class has not been
* defined in the present class loader. In case of a reloadable class loader,
* we prefer the base application class loader for proxying general classes
* not defined in the reloadable class loader itself.
* @return the original ClassLoader (the same reference by default)
* @since 5.3.5
* @see ClassLoader#getParent()
* @see org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
*/
default ClassLoader getOriginalClassLoader() {
return (ClassLoader) this;
}
/**
* Define a custom class (typically a CGLIB proxy class) in this class loader.
* <p>This is a public equivalent of the protected