Enforce use of ClassLoader.loadClass in case of temporary ClassLoader

Issue: SPR-17452
This commit is contained in:
Juergen Hoeller
2018-11-05 17:44:46 +01:00
parent 2ac4355ec0
commit 5cd525a2b0

View File

@@ -1362,6 +1362,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
@Nullable
protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
try {
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
@@ -1391,13 +1392,16 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
throws ClassNotFoundException {
ClassLoader beanClassLoader = getBeanClassLoader();
ClassLoader classLoaderToUse = beanClassLoader;
ClassLoader dynamicLoader = beanClassLoader;
boolean freshResolve = false;
if (!ObjectUtils.isEmpty(typesToMatch)) {
// When just doing type checks (i.e. not creating an actual instance yet),
// use the specified temporary class loader (e.g. in a weaving scenario).
ClassLoader tempClassLoader = getTempClassLoader();
if (tempClassLoader != null) {
classLoaderToUse = tempClassLoader;
dynamicLoader = tempClassLoader;
freshResolve = true;
if (tempClassLoader instanceof DecoratingClassLoader) {
DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
for (Class<?> typeToMatch : typesToMatch) {
@@ -1406,6 +1410,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
}
}
}
String className = mbd.getBeanClassName();
if (className != null) {
Object evaluated = evaluateBeanDefinitionString(className, mbd);
@@ -1415,18 +1420,31 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
return (Class<?>) evaluated;
}
else if (evaluated instanceof String) {
return ClassUtils.forName((String) evaluated, classLoaderToUse);
className = (String) evaluated;
freshResolve = true;
}
else {
throw new IllegalStateException("Invalid class name expression result: " + evaluated);
}
}
// When resolving against a temporary class loader, exit early in order
// to avoid storing the resolved Class in the bean definition.
if (classLoaderToUse != beanClassLoader) {
return ClassUtils.forName(className, classLoaderToUse);
if (freshResolve) {
// When resolving against a temporary class loader, exit early in order
// to avoid storing the resolved Class in the bean definition.
if (dynamicLoader != null) {
try {
return dynamicLoader.loadClass(className);
}
catch (ClassNotFoundException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
}
}
}
return ClassUtils.forName(className, dynamicLoader);
}
}
// Resolve regularly, caching the result in the BeanDefinition...
return mbd.resolveBeanClass(beanClassLoader);
}