16
16
17
17
package org .springframework .context .support ;
18
18
19
+ import java .lang .reflect .Proxy ;
19
20
import java .nio .file .InvalidPathException ;
21
+ import java .util .HashMap ;
22
+ import java .util .Map ;
20
23
21
24
import org .junit .jupiter .api .AfterEach ;
22
25
import org .junit .jupiter .api .Test ;
23
26
import org .junit .jupiter .api .condition .OS ;
24
27
import org .mockito .ArgumentCaptor ;
25
28
29
+ import org .springframework .aot .hint .RuntimeHints ;
30
+ import org .springframework .aot .hint .predicate .RuntimeHintsPredicates ;
26
31
import org .springframework .beans .BeansException ;
27
32
import org .springframework .beans .factory .NoUniqueBeanDefinitionException ;
28
33
import org .springframework .beans .factory .config .AbstractFactoryBean ;
29
34
import org .springframework .beans .factory .config .BeanDefinition ;
30
35
import org .springframework .beans .factory .config .BeanFactoryPostProcessor ;
36
+ import org .springframework .beans .factory .config .SmartInstantiationAwareBeanPostProcessor ;
31
37
import org .springframework .beans .factory .support .AbstractBeanDefinition ;
32
38
import org .springframework .beans .factory .support .BeanDefinitionBuilder ;
33
39
import org .springframework .beans .factory .support .GenericBeanDefinition ;
34
40
import org .springframework .beans .factory .support .MergedBeanDefinitionPostProcessor ;
35
41
import org .springframework .beans .factory .support .RootBeanDefinition ;
36
42
import org .springframework .context .ApplicationContext ;
37
43
import org .springframework .context .ApplicationContextAware ;
44
+ import org .springframework .core .DecoratingProxy ;
38
45
import org .springframework .core .env .ConfigurableEnvironment ;
39
46
import org .springframework .core .env .Environment ;
40
47
import org .springframework .core .io .ByteArrayResource ;
@@ -296,7 +303,7 @@ private void assertGetResourceSemantics(ResourceLoader resourceLoader, Class<? e
296
303
void refreshForAotSetsContextActive () {
297
304
GenericApplicationContext context = new GenericApplicationContext ();
298
305
assertThat (context .isActive ()).isFalse ();
299
- context .refreshForAotProcessing ();
306
+ context .refreshForAotProcessing (new RuntimeHints () );
300
307
assertThat (context .isActive ()).isTrue ();
301
308
context .close ();
302
309
}
@@ -306,7 +313,7 @@ void refreshForAotRegistersEnvironment() {
306
313
ConfigurableEnvironment environment = mock (ConfigurableEnvironment .class );
307
314
GenericApplicationContext context = new GenericApplicationContext ();
308
315
context .setEnvironment (environment );
309
- context .refreshForAotProcessing ();
316
+ context .refreshForAotProcessing (new RuntimeHints () );
310
317
assertThat (context .getBean (Environment .class )).isEqualTo (environment );
311
318
context .close ();
312
319
}
@@ -315,7 +322,7 @@ void refreshForAotRegistersEnvironment() {
315
322
void refreshForAotLoadsBeanClassName () {
316
323
GenericApplicationContext context = new GenericApplicationContext ();
317
324
context .registerBeanDefinition ("number" , new RootBeanDefinition ("java.lang.Integer" ));
318
- context .refreshForAotProcessing ();
325
+ context .refreshForAotProcessing (new RuntimeHints () );
319
326
assertThat (getBeanDefinition (context , "number" ).getBeanClass ()).isEqualTo (Integer .class );
320
327
context .close ();
321
328
}
@@ -328,7 +335,7 @@ void refreshForAotLoadsBeanClassNameOfConstructorArgumentInnerBeanDefinition() {
328
335
innerBeanDefinition .setBeanClassName ("java.lang.Integer" );
329
336
beanDefinition .getConstructorArgumentValues ().addIndexedArgumentValue (0 , innerBeanDefinition );
330
337
context .registerBeanDefinition ("test" ,beanDefinition );
331
- context .refreshForAotProcessing ();
338
+ context .refreshForAotProcessing (new RuntimeHints () );
332
339
RootBeanDefinition bd = getBeanDefinition (context , "test" );
333
340
GenericBeanDefinition value = (GenericBeanDefinition ) bd .getConstructorArgumentValues ()
334
341
.getIndexedArgumentValue (0 , GenericBeanDefinition .class ).getValue ();
@@ -345,7 +352,7 @@ void refreshForAotLoadsBeanClassNameOfPropertyValueInnerBeanDefinition() {
345
352
innerBeanDefinition .setBeanClassName ("java.lang.Integer" );
346
353
beanDefinition .getPropertyValues ().add ("inner" , innerBeanDefinition );
347
354
context .registerBeanDefinition ("test" ,beanDefinition );
348
- context .refreshForAotProcessing ();
355
+ context .refreshForAotProcessing (new RuntimeHints () );
349
356
RootBeanDefinition bd = getBeanDefinition (context , "test" );
350
357
GenericBeanDefinition value = (GenericBeanDefinition ) bd .getPropertyValues ().get ("inner" );
351
358
assertThat (value .hasBeanClass ()).isTrue ();
@@ -358,7 +365,7 @@ void refreshForAotInvokesBeanFactoryPostProcessors() {
358
365
GenericApplicationContext context = new GenericApplicationContext ();
359
366
BeanFactoryPostProcessor bfpp = mock (BeanFactoryPostProcessor .class );
360
367
context .addBeanFactoryPostProcessor (bfpp );
361
- context .refreshForAotProcessing ();
368
+ context .refreshForAotProcessing (new RuntimeHints () );
362
369
verify (bfpp ).postProcessBeanFactory (context .getBeanFactory ());
363
370
context .close ();
364
371
}
@@ -369,7 +376,7 @@ void refreshForAotInvokesMergedBeanDefinitionPostProcessors() {
369
376
context .registerBeanDefinition ("test" , new RootBeanDefinition (String .class ));
370
377
context .registerBeanDefinition ("number" , new RootBeanDefinition ("java.lang.Integer" ));
371
378
MergedBeanDefinitionPostProcessor bpp = registerMockMergedBeanDefinitionPostProcessor (context );
372
- context .refreshForAotProcessing ();
379
+ context .refreshForAotProcessing (new RuntimeHints () );
373
380
verify (bpp ).postProcessMergedBeanDefinition (getBeanDefinition (context , "test" ), String .class , "test" );
374
381
verify (bpp ).postProcessMergedBeanDefinition (getBeanDefinition (context , "number" ), Integer .class , "number" );
375
382
context .close ();
@@ -384,7 +391,7 @@ void refreshForAotInvokesMergedBeanDefinitionPostProcessorsOnConstructorArgument
384
391
beanDefinition .getConstructorArgumentValues ().addIndexedArgumentValue (0 , innerBeanDefinition );
385
392
context .registerBeanDefinition ("test" , beanDefinition );
386
393
MergedBeanDefinitionPostProcessor bpp = registerMockMergedBeanDefinitionPostProcessor (context );
387
- context .refreshForAotProcessing ();
394
+ context .refreshForAotProcessing (new RuntimeHints () );
388
395
ArgumentCaptor <String > captor = ArgumentCaptor .forClass (String .class );
389
396
verify (bpp ).postProcessMergedBeanDefinition (getBeanDefinition (context , "test" ), BeanD .class , "test" );
390
397
verify (bpp ).postProcessMergedBeanDefinition (any (RootBeanDefinition .class ), eq (Integer .class ), captor .capture ());
@@ -401,7 +408,7 @@ void refreshForAotInvokesMergedBeanDefinitionPostProcessorsOnPropertyValue() {
401
408
beanDefinition .getPropertyValues ().add ("counter" , innerBeanDefinition );
402
409
context .registerBeanDefinition ("test" , beanDefinition );
403
410
MergedBeanDefinitionPostProcessor bpp = registerMockMergedBeanDefinitionPostProcessor (context );
404
- context .refreshForAotProcessing ();
411
+ context .refreshForAotProcessing (new RuntimeHints () );
405
412
ArgumentCaptor <String > captor = ArgumentCaptor .forClass (String .class );
406
413
verify (bpp ).postProcessMergedBeanDefinition (getBeanDefinition (context , "test" ), BeanD .class , "test" );
407
414
verify (bpp ).postProcessMergedBeanDefinition (any (RootBeanDefinition .class ), eq (Integer .class ), captor .capture ());
@@ -414,7 +421,7 @@ void refreshForAotFreezeConfiguration() {
414
421
GenericApplicationContext context = new GenericApplicationContext ();
415
422
context .registerBeanDefinition ("test" , new RootBeanDefinition (String .class ));
416
423
MergedBeanDefinitionPostProcessor bpp = registerMockMergedBeanDefinitionPostProcessor (context );
417
- context .refreshForAotProcessing ();
424
+ context .refreshForAotProcessing (new RuntimeHints () );
418
425
RootBeanDefinition mergedBeanDefinition = getBeanDefinition (context , "test" );
419
426
verify (bpp ).postProcessMergedBeanDefinition (mergedBeanDefinition , String .class , "test" );
420
427
context .getBeanFactory ().clearMetadataCache ();
@@ -442,7 +449,7 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro
442
449
AbstractBeanDefinition bd = BeanDefinitionBuilder .rootBeanDefinition (String .class )
443
450
.addConstructorArgValue ("value" ).getBeanDefinition ();
444
451
context .registerBeanDefinition ("test" , bd );
445
- context .refreshForAotProcessing ();
452
+ context .refreshForAotProcessing (new RuntimeHints () );
446
453
assertThat (context .getBeanFactory ().getMergedBeanDefinition ("test" )
447
454
.hasAttribute ("mbdppCalled" )).isTrue ();
448
455
assertThat (context .getBean ("test" )).isEqualTo ("42" );
@@ -453,7 +460,7 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) thro
453
460
void refreshForAotFailsOnAnActiveContext () {
454
461
GenericApplicationContext context = new GenericApplicationContext ();
455
462
context .refresh ();
456
- assertThatIllegalStateException ().isThrownBy (context :: refreshForAotProcessing )
463
+ assertThatIllegalStateException ().isThrownBy (() -> context . refreshForAotProcessing ( new RuntimeHints ()) )
457
464
.withMessageContaining ("does not support multiple refresh attempts" );
458
465
context .close ();
459
466
}
@@ -463,7 +470,7 @@ void refreshForAotDoesNotInitializeFactoryBeansEarly() {
463
470
GenericApplicationContext context = new GenericApplicationContext ();
464
471
context .registerBeanDefinition ("genericFactoryBean" ,
465
472
new RootBeanDefinition (TestAotFactoryBean .class ));
466
- context .refreshForAotProcessing ();
473
+ context .refreshForAotProcessing (new RuntimeHints () );
467
474
context .close ();
468
475
}
469
476
@@ -473,7 +480,32 @@ void refreshForAotDoesNotInstantiateBean() {
473
480
context .registerBeanDefinition ("test" , BeanDefinitionBuilder .rootBeanDefinition (String .class , () -> {
474
481
throw new IllegalStateException ("Should not be invoked" );
475
482
}).getBeanDefinition ());
476
- context .refreshForAotProcessing ();
483
+ context .refreshForAotProcessing (new RuntimeHints ());
484
+ context .close ();
485
+ }
486
+
487
+ @ Test
488
+ void refreshForAotRegisterProxyHint () {
489
+ GenericApplicationContext context = new GenericApplicationContext ();
490
+ context .registerBeanDefinition ("bpp" , BeanDefinitionBuilder .rootBeanDefinition (
491
+ SmartInstantiationAwareBeanPostProcessor .class , () -> new SmartInstantiationAwareBeanPostProcessor () {
492
+ @ Override
493
+ public Class <?> determineBeanType (Class <?> beanClass , String beanName ) throws BeansException {
494
+ if (beanClass .isInterface ()) {
495
+ return Proxy .newProxyInstance (GenericApplicationContextTests .class .getClassLoader (),
496
+ new Class [] { Map .class , DecoratingProxy .class }, (proxy , method , args ) -> null ).getClass ();
497
+ }
498
+ else {
499
+ return beanClass ;
500
+ }
501
+ }
502
+ })
503
+ .setRole (BeanDefinition .ROLE_INFRASTRUCTURE ).getBeanDefinition ());
504
+ context .registerBeanDefinition ("map" , BeanDefinitionBuilder .rootBeanDefinition (Map .class ,
505
+ HashMap ::new ).getBeanDefinition ());
506
+ RuntimeHints runtimeHints = new RuntimeHints ();
507
+ context .refreshForAotProcessing (runtimeHints );
508
+ assertThat (RuntimeHintsPredicates .proxies ().forInterfaces (Map .class , DecoratingProxy .class )).accepts (runtimeHints );
477
509
context .close ();
478
510
}
479
511
0 commit comments