Skip to content

Commit b73ca60

Browse files
committed
Only attempt load for CGLIB classes in AOT mode
Closes gh-34677 (cherry picked from commit 743f326)
1 parent d689629 commit b73ca60

File tree

5 files changed

+23
-23
lines changed

5 files changed

+23
-23
lines changed

Diff for: spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
3535
import org.springframework.aop.RawTargetAccess;
3636
import org.springframework.aop.TargetSource;
3737
import org.springframework.aop.support.AopUtils;
38+
import org.springframework.aot.AotDetector;
3839
import org.springframework.cglib.core.ClassLoaderAwareGeneratorStrategy;
3940
import org.springframework.cglib.core.CodeGenerationException;
4041
import org.springframework.cglib.core.SpringNamingPolicy;
@@ -201,7 +202,7 @@ private Object buildProxy(@Nullable ClassLoader classLoader, boolean classOnly)
201202
enhancer.setSuperclass(proxySuperClass);
202203
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
203204
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
204-
enhancer.setAttemptLoad(true);
205+
enhancer.setAttemptLoad(enhancer.getUseCache() && AotDetector.useGeneratedArtifacts());
205206
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
206207

207208
Callback[] callbacks = getCallbacks(rootClass);

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222
import org.apache.commons.logging.Log;
2323
import org.apache.commons.logging.LogFactory;
2424

25+
import org.springframework.aot.AotDetector;
2526
import org.springframework.beans.BeanInstantiationException;
2627
import org.springframework.beans.BeanUtils;
2728
import org.springframework.beans.factory.BeanFactory;
@@ -153,7 +154,7 @@ public Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
153154
Enhancer enhancer = new Enhancer();
154155
enhancer.setSuperclass(beanDefinition.getBeanClass());
155156
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
156-
enhancer.setAttemptLoad(true);
157+
enhancer.setAttemptLoad(AotDetector.useGeneratedArtifacts());
157158
if (this.owner instanceof ConfigurableBeanFactory cbf) {
158159
ClassLoader cl = cbf.getBeanClassLoader();
159160
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
@@ -265,7 +266,7 @@ public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp
265266

266267
/**
267268
* CGLIB MethodInterceptor to override methods, replacing them with a call
268-
* to a generic MethodReplacer.
269+
* to a generic {@link MethodReplacer}.
269270
*/
270271
private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
271272

@@ -277,10 +278,10 @@ public ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanF
277278
}
278279

279280
@Override
281+
@Nullable
280282
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
281283
ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
282284
Assert.state(ro != null, "ReplaceOverride not found");
283-
// TODO could cache if a singleton for minor performance optimization
284285
MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
285286
return mr.reimplement(obj, method, args);
286287
}

Diff for: spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java

+7-10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.apache.commons.logging.LogFactory;
2727

2828
import org.springframework.aop.scope.ScopedProxyFactoryBean;
29+
import org.springframework.aot.AotDetector;
2930
import org.springframework.asm.Opcodes;
3031
import org.springframework.asm.Type;
3132
import org.springframework.beans.factory.BeanDefinitionStoreException;
@@ -138,26 +139,22 @@ private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader cl
138139
Enhancer enhancer = new Enhancer();
139140
if (classLoader != null) {
140141
enhancer.setClassLoader(classLoader);
142+
if (classLoader instanceof SmartClassLoader smartClassLoader &&
143+
smartClassLoader.isClassReloadable(configSuperClass)) {
144+
enhancer.setUseCache(false);
145+
}
141146
}
142147
enhancer.setSuperclass(configSuperClass);
143148
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
144149
enhancer.setUseFactory(false);
145150
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
146-
enhancer.setAttemptLoad(!isClassReloadable(configSuperClass, classLoader));
151+
enhancer.setAttemptLoad(enhancer.getUseCache() && AotDetector.useGeneratedArtifacts());
147152
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
148153
enhancer.setCallbackFilter(CALLBACK_FILTER);
149154
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
150155
return enhancer;
151156
}
152157

153-
/**
154-
* Checks whether the given configuration class is reloadable.
155-
*/
156-
private boolean isClassReloadable(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
157-
return (classLoader instanceof SmartClassLoader smartClassLoader &&
158-
smartClassLoader.isClassReloadable(configSuperClass));
159-
}
160-
161158
/**
162159
* Uses enhancer to generate a subclass of superclass,
163160
* ensuring that callbacks are registered for the new subclass.
@@ -548,7 +545,7 @@ private Object createCglibProxyForFactoryBean(Object factoryBean,
548545
Enhancer enhancer = new Enhancer();
549546
enhancer.setSuperclass(factoryBean.getClass());
550547
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
551-
enhancer.setAttemptLoad(true);
548+
enhancer.setAttemptLoad(AotDetector.useGeneratedArtifacts());
552549
enhancer.setCallbackType(MethodInterceptor.class);
553550

554551
// Ideally create enhanced FactoryBean proxy without constructor side effects,

Diff for: spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassEnhancerTests.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ void withPublicClass() {
7676
classLoader = new BasicSmartClassLoader(getClass().getClassLoader());
7777
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithPublicClass.class, classLoader);
7878
assertThat(MyConfigWithPublicClass.class).isAssignableFrom(enhancedClass);
79-
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
79+
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader);
8080
}
8181

8282
@Test
@@ -126,7 +126,7 @@ void withNonPublicMethod() {
126126
classLoader = new BasicSmartClassLoader(getClass().getClassLoader());
127127
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicMethod.class, classLoader);
128128
assertThat(MyConfigWithNonPublicMethod.class).isAssignableFrom(enhancedClass);
129-
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
129+
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader);
130130
}
131131

132132

Diff for: spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.commons.logging.Log;
3030
import org.apache.commons.logging.LogFactory;
3131

32+
import org.springframework.aot.AotDetector;
3233
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
3334
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
3435
import org.springframework.cglib.core.SpringNamingPolicy;
@@ -139,7 +140,7 @@ protected MvcUriComponentsBuilder(UriComponentsBuilder baseUrl) {
139140

140141
/**
141142
* Create an instance of this class with a base URL. After that calls to one
142-
* of the instance based {@code withXxx(...}} methods will create URLs relative
143+
* of the instance based {@code withXxx(...)} methods will create URLs relative
143144
* to the given base URL.
144145
*/
145146
public static MvcUriComponentsBuilder relativeTo(UriComponentsBuilder baseUrl) {
@@ -463,7 +464,7 @@ public UriComponentsBuilder withController(Class<?> controllerType) {
463464
}
464465

465466
/**
466-
* An alternative to {@link #fromMethodName(Class, String, Object...)}} for
467+
* An alternative to {@link #fromMethodName(Class, String, Object...)} for
467468
* use with an instance of this class created via {@link #relativeTo}.
468469
* @since 4.2
469470
*/
@@ -631,8 +632,8 @@ private static CompositeUriComponentsContributor getUriComponentsContributor() {
631632
private static String resolveEmbeddedValue(String value) {
632633
if (value.contains(SystemPropertyUtils.PLACEHOLDER_PREFIX)) {
633634
WebApplicationContext webApplicationContext = getWebApplicationContext();
634-
if (webApplicationContext != null
635-
&& webApplicationContext.getAutowireCapableBeanFactory() instanceof ConfigurableBeanFactory cbf) {
635+
if (webApplicationContext != null &&
636+
webApplicationContext.getAutowireCapableBeanFactory() instanceof ConfigurableBeanFactory cbf) {
636637
String resolvedEmbeddedValue = cbf.resolveEmbeddedValue(value);
637638
if (resolvedEmbeddedValue != null) {
638639
return resolvedEmbeddedValue;
@@ -793,7 +794,7 @@ else if (classLoader.getParent() == null) {
793794
enhancer.setSuperclass(controllerType);
794795
enhancer.setInterfaces(new Class<?>[] {MethodInvocationInfo.class});
795796
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
796-
enhancer.setAttemptLoad(true);
797+
enhancer.setAttemptLoad(AotDetector.useGeneratedArtifacts());
797798
enhancer.setCallbackType(MethodInterceptor.class);
798799

799800
Class<?> proxyClass = enhancer.createClass();

0 commit comments

Comments
 (0)