From e53cce0778f01fcced645cd831399b876fc2579c Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 25 Feb 2021 17:48:01 +0100 Subject: [PATCH] Allow AOP proxies to be created using the original ClassLoader Closes gh-26601 --- .../autoproxy/AbstractAutoProxyCreator.java | 9 ++++++-- .../core/SmartClassLoader.java | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java index d4ffb04faf1..2e48cbb1b0d 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java @@ -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); } /** diff --git a/spring-core/src/main/java/org/springframework/core/SmartClassLoader.java b/spring-core/src/main/java/org/springframework/core/SmartClassLoader.java index fe7d3637090..e6a39c149ec 100644 --- a/spring-core/src/main/java/org/springframework/core/SmartClassLoader.java +++ b/spring-core/src/main/java/org/springframework/core/SmartClassLoader.java @@ -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. + *

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();}). + *

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. *

This is a public equivalent of the protected