@ -84,6 +84,7 @@ import org.springframework.context.testfixture.context.annotation.LazyResourceMe
@@ -84,6 +84,7 @@ import org.springframework.context.testfixture.context.annotation.LazyResourceMe
import org.springframework.context.testfixture.context.annotation.PropertySourceConfiguration ;
import org.springframework.context.testfixture.context.annotation.QualifierConfiguration ;
import org.springframework.context.testfixture.context.annotation.ResourceComponent ;
import org.springframework.context.testfixture.context.annotation.ValueCglibConfiguration ;
import org.springframework.context.testfixture.context.generator.SimpleComponent ;
import org.springframework.core.env.ConfigurableEnvironment ;
import org.springframework.core.env.Environment ;
@ -438,12 +439,14 @@ class ApplicationContextAotGeneratorTests {
@@ -438,12 +439,14 @@ class ApplicationContextAotGeneratorTests {
@CompileWithForkedClassLoader
class ConfigurationClassCglibProxy {
private static final String CGLIB_CONFIGURATION_CLASS_SUFFIX = "$$SpringCGLIB$$0" ;
@Test
void processAheadOfTimeWhenHasCglibProxyWriteProxyAndGenerateReflectionHints ( ) throws IOException {
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ( ) ;
applicationContext . registerBean ( CglibConfiguration . class ) ;
TestGenerationContext context = processAheadOfTime ( applicationContext ) ;
isRegisteredCglibClass ( context , CglibConfiguration . class . getName ( ) + "$$SpringCGLIB$$0" ) ;
isRegisteredCglibClass ( context , CglibConfiguration . class . getName ( ) + CGLIB_CONFIGURATION_CLASS_SUFFIX ) ;
isRegisteredCglibClass ( context , CglibConfiguration . class . getName ( ) + "$$SpringCGLIB$$FastClass$$0" ) ;
isRegisteredCglibClass ( context , CglibConfiguration . class . getName ( ) + "$$SpringCGLIB$$FastClass$$1" ) ;
}
@ -455,6 +458,43 @@ class ApplicationContextAotGeneratorTests {
@@ -455,6 +458,43 @@ class ApplicationContextAotGeneratorTests {
. withMemberCategory ( MemberCategory . INVOKE_DECLARED_CONSTRUCTORS ) ) . accepts ( context . getRuntimeHints ( ) ) ;
}
@Test
void processAheadOfTimeExposeUserClassForCglibProxy ( ) {
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ( ) ;
applicationContext . registerBean ( "config" , ValueCglibConfiguration . class ) ;
testCompiledResult ( applicationContext , ( initializer , compiled ) - > {
GenericApplicationContext freshApplicationContext = toFreshApplicationContext ( initializer ) ;
assertThat ( freshApplicationContext ) . satisfies ( hasBeanDefinitionOfBeanClass ( "config" , ValueCglibConfiguration . class ) ) ;
assertThat ( compiled . getSourceFile ( ".*ValueCglibConfiguration__BeanDefinitions" ) )
. contains ( "new RootBeanDefinition(ValueCglibConfiguration.class)" )
. contains ( "new %s(" . formatted ( toCglibClassSimpleName ( ValueCglibConfiguration . class ) ) ) ;
} ) ;
}
@Test
void processAheadOfTimeUsesCglibClassForFactoryMethod ( ) {
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ( ) ;
applicationContext . registerBean ( "config" , CglibConfiguration . class ) ;
testCompiledResult ( applicationContext , ( initializer , compiled ) - > {
GenericApplicationContext freshApplicationContext = toFreshApplicationContext ( initializer ) ;
assertThat ( freshApplicationContext ) . satisfies ( hasBeanDefinitionOfBeanClass ( "config" , CglibConfiguration . class ) ) ;
assertThat ( compiled . getSourceFile ( ".*CglibConfiguration__BeanDefinitions" ) )
. contains ( "new RootBeanDefinition(CglibConfiguration.class)" )
. contains ( ">forFactoryMethod(%s.class," . formatted ( toCglibClassSimpleName ( CglibConfiguration . class ) ) )
. doesNotContain ( ">forFactoryMethod(%s.class," . formatted ( CglibConfiguration . class ) ) ;
} ) ;
}
private Consumer < GenericApplicationContext > hasBeanDefinitionOfBeanClass ( String name , Class < ? > beanClass ) {
return context - > {
assertThat ( context . containsBean ( name ) ) . isTrue ( ) ;
assertThat ( context . getBeanDefinition ( name ) ) . isInstanceOfSatisfying ( RootBeanDefinition . class ,
rbd - > assertThat ( rbd . getBeanClass ( ) ) . isEqualTo ( beanClass ) ) ;
} ;
}
@Test
void processAheadOfTimeWhenHasCglibProxyUseProxy ( ) {
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ( ) ;
@ -493,6 +533,20 @@ class ApplicationContextAotGeneratorTests {
@@ -493,6 +533,20 @@ class ApplicationContextAotGeneratorTests {
} ) ;
}
@Test
void processAheadOfTimeWhenHasCglibProxyWithAnnotationsOnTheUserClasConstructor ( ) {
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ( ) ;
applicationContext . registerBean ( "config" , ValueCglibConfiguration . class ) ;
testCompiledResult ( applicationContext , ( initializer , compiled ) - > {
GenericApplicationContext freshApplicationContext = toFreshApplicationContext ( context - > {
context . setEnvironment ( new MockEnvironment ( ) . withProperty ( "name" , "AOT World" ) ) ;
initializer . initialize ( context ) ;
} ) ;
assertThat ( freshApplicationContext . getBean ( ValueCglibConfiguration . class )
. getName ( ) ) . isEqualTo ( "AOT World" ) ;
} ) ;
}
@Test
void processAheadOfTimeWhenHasCglibProxyWithArgumentsUseProxy ( ) {
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ( ) ;
@ -516,6 +570,10 @@ class ApplicationContextAotGeneratorTests {
@@ -516,6 +570,10 @@ class ApplicationContextAotGeneratorTests {
. accepts ( generationContext . getRuntimeHints ( ) ) ;
}
private String toCglibClassSimpleName ( Class < ? > configClass ) {
return configClass . getSimpleName ( ) + CGLIB_CONFIGURATION_CLASS_SUFFIX ;
}
}
@Nested