@ -22,6 +22,7 @@ import java.util.List;
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.function.BiConsumer ;
import java.util.function.Consumer ;
import org.junit.jupiter.api.Nested ;
import org.junit.jupiter.api.Test ;
import org.springframework.aot.generate.GeneratedFiles.Kind ;
@ -54,6 +55,7 @@ import org.springframework.context.support.GenericApplicationContext;
@@ -54,6 +55,7 @@ import org.springframework.context.support.GenericApplicationContext;
import org.springframework.context.testfixture.context.generator.SimpleComponent ;
import org.springframework.context.testfixture.context.generator.annotation.AutowiredComponent ;
import org.springframework.context.testfixture.context.generator.annotation.CglibConfiguration ;
import org.springframework.context.testfixture.context.generator.annotation.ConfigurableCglibConfiguration ;
import org.springframework.context.testfixture.context.generator.annotation.InitDestroyComponent ;
import org.springframework.context.testfixture.context.generator.annotation.LazyAutowiredFieldComponent ;
import org.springframework.context.testfixture.context.generator.annotation.LazyAutowiredMethodComponent ;
@ -64,8 +66,10 @@ import org.springframework.core.env.ConfigurableEnvironment;
@@ -64,8 +66,10 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment ;
import org.springframework.core.env.PropertySource ;
import org.springframework.core.io.ResourceLoader ;
import org.springframework.core.test.tools.CompileWithForkedClassLoader ;
import org.springframework.core.test.tools.Compiled ;
import org.springframework.core.test.tools.TestCompiler ;
import org.springframework.mock.env.MockEnvironment ;
import static org.assertj.core.api.Assertions.assertThat ;
@ -93,13 +97,13 @@ class ApplicationContextAotGeneratorTests {
@@ -93,13 +97,13 @@ class ApplicationContextAotGeneratorTests {
GenericApplicationContext applicationContext = new GenericApplicationContext ( ) ;
applicationContext . registerBeanDefinition ( AnnotationConfigUtils . AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME ,
BeanDefinitionBuilder
. rootBeanDefinition ( AutowiredAnnotationBeanPostProcessor . class )
. setRole ( BeanDefinition . ROLE_INFRASTRUCTURE ) . getBeanDefinition ( ) ) ;
. rootBeanDefinition ( AutowiredAnnotationBeanPostProcessor . class )
. setRole ( BeanDefinition . ROLE_INFRASTRUCTURE ) . getBeanDefinition ( ) ) ;
applicationContext . registerBeanDefinition ( "autowiredComponent" , new RootBeanDefinition ( AutowiredComponent . class ) ) ;
applicationContext . registerBeanDefinition ( "number" ,
BeanDefinitionBuilder
. rootBeanDefinition ( Integer . class , "valueOf" )
. addConstructorArgValue ( "42" ) . getBeanDefinition ( ) ) ;
. rootBeanDefinition ( Integer . class , "valueOf" )
. addConstructorArgValue ( "42" ) . getBeanDefinition ( ) ) ;
testCompiledResult ( applicationContext , ( initializer , compiled ) - > {
GenericApplicationContext freshApplicationContext = toFreshApplicationContext ( initializer ) ;
assertThat ( freshApplicationContext . getBeanDefinitionNames ( ) ) . containsOnly ( "autowiredComponent" , "number" ) ;
@ -200,8 +204,8 @@ class ApplicationContextAotGeneratorTests {
@@ -200,8 +204,8 @@ class ApplicationContextAotGeneratorTests {
applicationContext . registerBeanDefinition (
AnnotationConfigUtils . COMMON_ANNOTATION_PROCESSOR_BEAN_NAME ,
BeanDefinitionBuilder
. rootBeanDefinition ( CommonAnnotationBeanPostProcessor . class )
. setRole ( BeanDefinition . ROLE_INFRASTRUCTURE ) . getBeanDefinition ( ) ) ;
. rootBeanDefinition ( CommonAnnotationBeanPostProcessor . class )
. setRole ( BeanDefinition . ROLE_INFRASTRUCTURE ) . getBeanDefinition ( ) ) ;
applicationContext . registerBeanDefinition ( "initDestroyComponent" ,
new RootBeanDefinition ( InitDestroyComponent . class ) ) ;
testCompiledResult ( applicationContext , ( initializer , compiled ) - > {
@ -220,8 +224,8 @@ class ApplicationContextAotGeneratorTests {
@@ -220,8 +224,8 @@ class ApplicationContextAotGeneratorTests {
applicationContext . registerBeanDefinition (
AnnotationConfigUtils . COMMON_ANNOTATION_PROCESSOR_BEAN_NAME ,
BeanDefinitionBuilder
. rootBeanDefinition ( CommonAnnotationBeanPostProcessor . class )
. setRole ( BeanDefinition . ROLE_INFRASTRUCTURE ) . getBeanDefinition ( ) ) ;
. rootBeanDefinition ( CommonAnnotationBeanPostProcessor . class )
. setRole ( BeanDefinition . ROLE_INFRASTRUCTURE ) . getBeanDefinition ( ) ) ;
RootBeanDefinition beanDefinition = new RootBeanDefinition ( InitDestroyComponent . class ) ;
beanDefinition . setInitMethodName ( "customInit" ) ;
beanDefinition . setDestroyMethodName ( "customDestroy" ) ;
@ -270,17 +274,6 @@ class ApplicationContextAotGeneratorTests {
@@ -270,17 +274,6 @@ class ApplicationContextAotGeneratorTests {
} ) ;
}
@Test
void processAheadOfTimeWhenHasCglibProxyWriteProxyAndGenerateReflectionHints ( ) throws IOException {
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ( ) ;
applicationContext . registerBean ( CglibConfiguration . class ) ;
TestGenerationContext context = processAheadOfTime ( applicationContext ) ;
String proxyClassName = CglibConfiguration . class . getName ( ) + "$$SpringCGLIB$$0" ;
assertThat ( context . getGeneratedFiles ( )
. getGeneratedFileContent ( Kind . CLASS , proxyClassName . replace ( '.' , '/' ) + ".class" ) ) . isNotNull ( ) ;
assertThat ( RuntimeHintsPredicates . reflection ( ) . onType ( TypeReference . of ( proxyClassName ) )
. withMemberCategory ( MemberCategory . INVOKE_DECLARED_CONSTRUCTORS ) ) . accepts ( context . getRuntimeHints ( ) ) ;
}
@Test
void processAheadOfTimeWithPropertySource ( ) {
@ -295,8 +288,51 @@ class ApplicationContextAotGeneratorTests {
@@ -295,8 +288,51 @@ class ApplicationContextAotGeneratorTests {
} ) ;
}
@Nested
@CompileWithForkedClassLoader
class ConfigurationClassCglibProxy {
@Test
void processAheadOfTimeWhenHasCglibProxyWriteProxyAndGenerateReflectionHints ( ) throws IOException {
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ( ) ;
applicationContext . registerBean ( CglibConfiguration . class ) ;
TestGenerationContext context = processAheadOfTime ( applicationContext ) ;
String proxyClassName = CglibConfiguration . class . getName ( ) + "$$SpringCGLIB$$0" ;
assertThat ( context . getGeneratedFiles ( )
. getGeneratedFileContent ( Kind . CLASS , proxyClassName . replace ( '.' , '/' ) + ".class" ) ) . isNotNull ( ) ;
assertThat ( RuntimeHintsPredicates . reflection ( ) . onType ( TypeReference . of ( proxyClassName ) )
. withMemberCategory ( MemberCategory . INVOKE_DECLARED_CONSTRUCTORS ) ) . accepts ( context . getRuntimeHints ( ) ) ;
}
@Test
void processAheadOfTimeWhenHasCglibProxyUseProxy ( ) {
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ( ) ;
applicationContext . registerBean ( CglibConfiguration . class ) ;
testCompiledResult ( applicationContext , ( initializer , compiled ) - > {
GenericApplicationContext freshApplicationContext = toFreshApplicationContext ( initializer ) ;
assertThat ( freshApplicationContext . getBean ( "prefix" , String . class ) ) . isEqualTo ( "Hello0" ) ;
assertThat ( freshApplicationContext . getBean ( "text" , String . class ) ) . isEqualTo ( "Hello0 World" ) ;
} ) ;
}
@Test
void processAheadOfTimeWhenHasCglibProxyWithArgumentsUseProxy ( ) {
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ( ) ;
applicationContext . registerBean ( ConfigurableCglibConfiguration . class ) ;
testCompiledResult ( applicationContext , ( initializer , compiled ) - > {
GenericApplicationContext freshApplicationContext = createFreshApplicationContext ( initializer ) ;
freshApplicationContext . setEnvironment ( new MockEnvironment ( ) . withProperty ( "test.prefix" , "Hi" ) ) ;
freshApplicationContext . refresh ( ) ;
assertThat ( freshApplicationContext . getBean ( "prefix" , String . class ) ) . isEqualTo ( "Hi0" ) ;
assertThat ( freshApplicationContext . getBean ( "text" , String . class ) ) . isEqualTo ( "Hi0 World" ) ;
} ) ;
}
}
private Consumer < List < ? extends JdkProxyHint > > doesNotHaveProxyFor ( Class < ? > target ) {
return hints - > assertThat ( hints ) . noneMatch ( hint - > hint . getProxiedInterfaces ( ) . get ( 0 ) . equals ( target ) ) ;
return hints - > assertThat ( hints ) . noneMatch ( hint - >
hint . getProxiedInterfaces ( ) . get ( 0 ) . equals ( TypeReference . of ( target ) ) ) ;
}
private static TestGenerationContext processAheadOfTime ( GenericApplicationContext applicationContext ) {
@ -307,23 +343,29 @@ class ApplicationContextAotGeneratorTests {
@@ -307,23 +343,29 @@ class ApplicationContextAotGeneratorTests {
return generationContext ;
}
private void testCompiledResult ( GenericApplicationContext applicationContext ,
private static void testCompiledResult ( GenericApplicationContext applicationContext ,
BiConsumer < ApplicationContextInitializer < GenericApplicationContext > , Compiled > result ) {
testCompiledResult ( processAheadOfTime ( applicationContext ) , result ) ;
}
@SuppressWarnings ( { "rawtypes" , "unchecked" } )
private void testCompiledResult ( TestGenerationContext generationContext ,
private static void testCompiledResult ( TestGenerationContext generationContext ,
BiConsumer < ApplicationContextInitializer < GenericApplicationContext > , Compiled > result ) {
TestCompiler . forSystem ( ) . with ( generationContext ) . compile ( compiled - >
result . accept ( compiled . getInstance ( ApplicationContextInitializer . class ) , compiled ) ) ;
}
private GenericApplicationContext toFreshApplicationContext (
private static GenericApplicationContext toFreshApplicationContext (
ApplicationContextInitializer < GenericApplicationContext > initializer ) {
GenericApplicationContext freshApplicationContext = createFreshApplicationContext ( initializer ) ;
freshApplicationContext . refresh ( ) ;
return freshApplicationContext ;
}
private static GenericApplicationContext createFreshApplicationContext (
ApplicationContextInitializer < GenericApplicationContext > initializer ) {
GenericApplicationContext freshApplicationContext = new GenericApplicationContext ( ) ;
initializer . initialize ( freshApplicationContext ) ;
freshApplicationContext . refresh ( ) ;
return freshApplicationContext ;
}