84
84
import org .springframework .context .testfixture .context .annotation .PropertySourceConfiguration ;
85
85
import org .springframework .context .testfixture .context .annotation .QualifierConfiguration ;
86
86
import org .springframework .context .testfixture .context .annotation .ResourceComponent ;
87
+ import org .springframework .context .testfixture .context .annotation .ValueCglibConfiguration ;
87
88
import org .springframework .context .testfixture .context .generator .SimpleComponent ;
88
89
import org .springframework .core .env .ConfigurableEnvironment ;
89
90
import org .springframework .core .env .Environment ;
@@ -438,12 +439,14 @@ void processAheadOfTimeWithExplicitResolvableType() {
438
439
@ CompileWithForkedClassLoader
439
440
class ConfigurationClassCglibProxy {
440
441
442
+ private static final String CGLIB_CONFIGURATION_CLASS_SUFFIX = "$$SpringCGLIB$$0" ;
443
+
441
444
@ Test
442
445
void processAheadOfTimeWhenHasCglibProxyWriteProxyAndGenerateReflectionHints () throws IOException {
443
446
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ();
444
447
applicationContext .registerBean (CglibConfiguration .class );
445
448
TestGenerationContext context = processAheadOfTime (applicationContext );
446
- isRegisteredCglibClass (context , CglibConfiguration .class .getName () + "$$SpringCGLIB$$0" );
449
+ isRegisteredCglibClass (context , CglibConfiguration .class .getName () + CGLIB_CONFIGURATION_CLASS_SUFFIX );
447
450
isRegisteredCglibClass (context , CglibConfiguration .class .getName () + "$$SpringCGLIB$$FastClass$$0" );
448
451
isRegisteredCglibClass (context , CglibConfiguration .class .getName () + "$$SpringCGLIB$$FastClass$$1" );
449
452
}
@@ -455,6 +458,43 @@ private void isRegisteredCglibClass(TestGenerationContext context, String cglibC
455
458
.withMemberCategory (MemberCategory .INVOKE_DECLARED_CONSTRUCTORS )).accepts (context .getRuntimeHints ());
456
459
}
457
460
461
+ @ Test
462
+ void processAheadOfTimeExposeUserClassForCglibProxy () {
463
+ GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ();
464
+ applicationContext .registerBean ("config" , ValueCglibConfiguration .class );
465
+
466
+ testCompiledResult (applicationContext , (initializer , compiled ) -> {
467
+ GenericApplicationContext freshApplicationContext = toFreshApplicationContext (initializer );
468
+ assertThat (freshApplicationContext ).satisfies (hasBeanDefinitionOfBeanClass ("config" , ValueCglibConfiguration .class ));
469
+ assertThat (compiled .getSourceFile (".*ValueCglibConfiguration__BeanDefinitions" ))
470
+ .contains ("new RootBeanDefinition(ValueCglibConfiguration.class)" )
471
+ .contains ("new %s(" .formatted (toCglibClassSimpleName (ValueCglibConfiguration .class )));
472
+ });
473
+ }
474
+
475
+ @ Test
476
+ void processAheadOfTimeUsesCglibClassForFactoryMethod () {
477
+ GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ();
478
+ applicationContext .registerBean ("config" , CglibConfiguration .class );
479
+
480
+ testCompiledResult (applicationContext , (initializer , compiled ) -> {
481
+ GenericApplicationContext freshApplicationContext = toFreshApplicationContext (initializer );
482
+ assertThat (freshApplicationContext ).satisfies (hasBeanDefinitionOfBeanClass ("config" , CglibConfiguration .class ));
483
+ assertThat (compiled .getSourceFile (".*CglibConfiguration__BeanDefinitions" ))
484
+ .contains ("new RootBeanDefinition(CglibConfiguration.class)" )
485
+ .contains (">forFactoryMethod(%s.class," .formatted (toCglibClassSimpleName (CglibConfiguration .class )))
486
+ .doesNotContain (">forFactoryMethod(%s.class," .formatted (CglibConfiguration .class ));
487
+ });
488
+ }
489
+
490
+ private Consumer <GenericApplicationContext > hasBeanDefinitionOfBeanClass (String name , Class <?> beanClass ) {
491
+ return context -> {
492
+ assertThat (context .containsBean (name )).isTrue ();
493
+ assertThat (context .getBeanDefinition (name )).isInstanceOfSatisfying (RootBeanDefinition .class ,
494
+ rbd -> assertThat (rbd .getBeanClass ()).isEqualTo (beanClass ));
495
+ };
496
+ }
497
+
458
498
@ Test
459
499
void processAheadOfTimeWhenHasCglibProxyUseProxy () {
460
500
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ();
@@ -493,6 +533,20 @@ void processAheadOfTimeWhenHasCglibProxyAndMixedAutowiring() {
493
533
});
494
534
}
495
535
536
+ @ Test
537
+ void processAheadOfTimeWhenHasCglibProxyWithAnnotationsOnTheUserClasConstructor () {
538
+ GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ();
539
+ applicationContext .registerBean ("config" , ValueCglibConfiguration .class );
540
+ testCompiledResult (applicationContext , (initializer , compiled ) -> {
541
+ GenericApplicationContext freshApplicationContext = toFreshApplicationContext (context -> {
542
+ context .setEnvironment (new MockEnvironment ().withProperty ("name" , "AOT World" ));
543
+ initializer .initialize (context );
544
+ });
545
+ assertThat (freshApplicationContext .getBean (ValueCglibConfiguration .class )
546
+ .getName ()).isEqualTo ("AOT World" );
547
+ });
548
+ }
549
+
496
550
@ Test
497
551
void processAheadOfTimeWhenHasCglibProxyWithArgumentsUseProxy () {
498
552
GenericApplicationContext applicationContext = new AnnotationConfigApplicationContext ();
@@ -516,6 +570,10 @@ void processAheadOfTimeWhenHasCglibProxyWithArgumentsRegisterIntrospectionHintsO
516
570
.accepts (generationContext .getRuntimeHints ());
517
571
}
518
572
573
+ private String toCglibClassSimpleName (Class <?> configClass ) {
574
+ return configClass .getSimpleName () + CGLIB_CONFIGURATION_CLASS_SUFFIX ;
575
+ }
576
+
519
577
}
520
578
521
579
@ Nested
0 commit comments