Browse Source

Only attempt load for CGLIB classes in AOT mode

Closes gh-34677
pull/34732/head
Juergen Hoeller 9 months ago
parent
commit
743f32675d
  1. 5
      spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java
  2. 5
      spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java
  3. 17
      spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java
  4. 4
      spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassEnhancerTests.java
  5. 3
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java

5
spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2024 the original author or authors. * Copyright 2002-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -35,6 +35,7 @@ import org.springframework.aop.AopInvocationException;
import org.springframework.aop.RawTargetAccess; import org.springframework.aop.RawTargetAccess;
import org.springframework.aop.TargetSource; import org.springframework.aop.TargetSource;
import org.springframework.aop.support.AopUtils; import org.springframework.aop.support.AopUtils;
import org.springframework.aot.AotDetector;
import org.springframework.cglib.core.ClassLoaderAwareGeneratorStrategy; import org.springframework.cglib.core.ClassLoaderAwareGeneratorStrategy;
import org.springframework.cglib.core.CodeGenerationException; import org.springframework.cglib.core.CodeGenerationException;
import org.springframework.cglib.core.GeneratorStrategy; import org.springframework.cglib.core.GeneratorStrategy;
@ -205,7 +206,7 @@ class CglibAopProxy implements AopProxy, Serializable {
enhancer.setSuperclass(proxySuperClass); enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setAttemptLoad(true); enhancer.setAttemptLoad(enhancer.getUseCache() && AotDetector.useGeneratedArtifacts());
enhancer.setStrategy(KotlinDetector.isKotlinType(proxySuperClass) ? enhancer.setStrategy(KotlinDetector.isKotlinType(proxySuperClass) ?
new ClassLoaderAwareGeneratorStrategy(classLoader) : new ClassLoaderAwareGeneratorStrategy(classLoader) :
new ClassLoaderAwareGeneratorStrategy(classLoader, undeclaredThrowableStrategy) new ClassLoaderAwareGeneratorStrategy(classLoader, undeclaredThrowableStrategy)

5
spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2024 the original author or authors. * Copyright 2002-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,6 +22,7 @@ import java.lang.reflect.Method;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.aot.AotDetector;
import org.springframework.beans.BeanInstantiationException; import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
@ -153,7 +154,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
Enhancer enhancer = new Enhancer(); Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanDefinition.getBeanClass()); enhancer.setSuperclass(beanDefinition.getBeanClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setAttemptLoad(true); enhancer.setAttemptLoad(AotDetector.useGeneratedArtifacts());
if (this.owner instanceof ConfigurableBeanFactory cbf) { if (this.owner instanceof ConfigurableBeanFactory cbf) {
ClassLoader cl = cbf.getBeanClassLoader(); ClassLoader cl = cbf.getBeanClassLoader();
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl)); enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));

17
spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java

@ -26,6 +26,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.aop.scope.ScopedProxyFactoryBean; import org.springframework.aop.scope.ScopedProxyFactoryBean;
import org.springframework.aot.AotDetector;
import org.springframework.asm.Opcodes; import org.springframework.asm.Opcodes;
import org.springframework.asm.Type; import org.springframework.asm.Type;
import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanDefinitionStoreException;
@ -138,26 +139,22 @@ class ConfigurationClassEnhancer {
Enhancer enhancer = new Enhancer(); Enhancer enhancer = new Enhancer();
if (classLoader != null) { if (classLoader != null) {
enhancer.setClassLoader(classLoader); enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader smartClassLoader &&
smartClassLoader.isClassReloadable(configSuperClass)) {
enhancer.setUseCache(false);
}
} }
enhancer.setSuperclass(configSuperClass); enhancer.setSuperclass(configSuperClass);
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class}); enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false); enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setAttemptLoad(!isClassReloadable(configSuperClass, classLoader)); enhancer.setAttemptLoad(enhancer.getUseCache() && AotDetector.useGeneratedArtifacts());
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader)); enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
enhancer.setCallbackFilter(CALLBACK_FILTER); enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes()); enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer; return enhancer;
} }
/**
* Checks whether the given configuration class is reloadable.
*/
private boolean isClassReloadable(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
return (classLoader instanceof SmartClassLoader smartClassLoader &&
smartClassLoader.isClassReloadable(configSuperClass));
}
/** /**
* Uses enhancer to generate a subclass of superclass, * Uses enhancer to generate a subclass of superclass,
* ensuring that callbacks are registered for the new subclass. * ensuring that callbacks are registered for the new subclass.
@ -548,7 +545,7 @@ class ConfigurationClassEnhancer {
Enhancer enhancer = new Enhancer(); Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(factoryBean.getClass()); enhancer.setSuperclass(factoryBean.getClass());
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setAttemptLoad(true); enhancer.setAttemptLoad(AotDetector.useGeneratedArtifacts());
enhancer.setCallbackType(MethodInterceptor.class); enhancer.setCallbackType(MethodInterceptor.class);
// Ideally create enhanced FactoryBean proxy without constructor side effects, // Ideally create enhanced FactoryBean proxy without constructor side effects,

4
spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassEnhancerTests.java

@ -76,7 +76,7 @@ class ConfigurationClassEnhancerTests {
classLoader = new BasicSmartClassLoader(getClass().getClassLoader()); classLoader = new BasicSmartClassLoader(getClass().getClassLoader());
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithPublicClass.class, classLoader); enhancedClass = configurationClassEnhancer.enhance(MyConfigWithPublicClass.class, classLoader);
assertThat(MyConfigWithPublicClass.class).isAssignableFrom(enhancedClass); assertThat(MyConfigWithPublicClass.class).isAssignableFrom(enhancedClass);
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent()); assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader);
} }
@Test @Test
@ -126,7 +126,7 @@ class ConfigurationClassEnhancerTests {
classLoader = new BasicSmartClassLoader(getClass().getClassLoader()); classLoader = new BasicSmartClassLoader(getClass().getClassLoader());
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicMethod.class, classLoader); enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicMethod.class, classLoader);
assertThat(MyConfigWithNonPublicMethod.class).isAssignableFrom(enhancedClass); assertThat(MyConfigWithNonPublicMethod.class).isAssignableFrom(enhancedClass);
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent()); assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader);
} }

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

@ -29,6 +29,7 @@ import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.aot.AotDetector;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.cglib.core.SpringNamingPolicy; import org.springframework.cglib.core.SpringNamingPolicy;
@ -793,7 +794,7 @@ public class MvcUriComponentsBuilder {
enhancer.setSuperclass(controllerType); enhancer.setSuperclass(controllerType);
enhancer.setInterfaces(new Class<?>[] {MethodInvocationInfo.class}); enhancer.setInterfaces(new Class<?>[] {MethodInvocationInfo.class});
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setAttemptLoad(true); enhancer.setAttemptLoad(AotDetector.useGeneratedArtifacts());
enhancer.setCallbackType(MethodInterceptor.class); enhancer.setCallbackType(MethodInterceptor.class);
Class<?> proxyClass = enhancer.createClass(); Class<?> proxyClass = enhancer.createClass();

Loading…
Cancel
Save