1
1
/*
2
- * Copyright 2012-2020 the original author or authors.
2
+ * Copyright 2012-2024 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
16
16
17
17
package org .springframework .cloud .context .named ;
18
18
19
+ import java .lang .annotation .Documented ;
20
+ import java .lang .annotation .ElementType ;
21
+ import java .lang .annotation .Inherited ;
22
+ import java .lang .annotation .Retention ;
23
+ import java .lang .annotation .RetentionPolicy ;
24
+ import java .lang .annotation .Target ;
19
25
import java .util .Arrays ;
26
+ import java .util .List ;
20
27
import java .util .Map ;
21
28
import java .util .concurrent .ExecutionException ;
22
29
import java .util .concurrent .ExecutorService ;
23
30
import java .util .concurrent .Executors ;
24
31
import java .util .concurrent .TimeUnit ;
25
32
import java .util .concurrent .TimeoutException ;
26
33
27
- import org .assertj .core .api .Assertions ;
28
34
import org .junit .jupiter .api .Test ;
29
35
30
36
import org .springframework .boot .autoconfigure .condition .ConditionalOnClass ;
31
37
import org .springframework .context .annotation .AnnotationConfigApplicationContext ;
32
38
import org .springframework .context .annotation .Bean ;
33
39
import org .springframework .context .support .GenericApplicationContext ;
40
+ import org .springframework .core .ResolvableType ;
34
41
import org .springframework .util .ClassUtils ;
35
42
43
+ import static org .assertj .core .api .Assertions .assertThat ;
44
+ import static org .assertj .core .api .Assertions .assertThatIllegalStateException ;
36
45
import static org .assertj .core .api .BDDAssertions .then ;
37
46
38
47
/**
@@ -50,6 +59,64 @@ public void testChildContexts() {
50
59
testChildContexts (parent );
51
60
}
52
61
62
+ @ Test
63
+ void testBadThreadContextClassLoader () throws InterruptedException , ExecutionException , TimeoutException {
64
+ AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext ();
65
+ parent .setClassLoader (ClassUtils .getDefaultClassLoader ());
66
+ parent .register (BaseConfig .class );
67
+ parent .refresh ();
68
+
69
+ ExecutorService es = Executors .newSingleThreadExecutor (r -> {
70
+ Thread t = new Thread (r );
71
+ t .setContextClassLoader (new ThrowingClassLoader ());
72
+ return t ;
73
+ });
74
+ es .submit (() -> this .testChildContexts (parent )).get (5 , TimeUnit .SECONDS );
75
+
76
+ }
77
+
78
+ @ Test
79
+ void testGetAnnotatedBeanInstance () {
80
+ AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext ();
81
+ parent .register (BaseConfig .class );
82
+ parent .refresh ();
83
+ TestClientFactory factory = new TestClientFactory ();
84
+ factory .setApplicationContext (parent );
85
+ factory .setConfigurations (List .of (getSpec ("annotated" , AnnotatedConfig .class )));
86
+
87
+ TestType annotatedBean = factory .getAnnotatedInstance ("annotated" , ResolvableType .forType (TestType .class ),
88
+ TestBean .class );
89
+
90
+ assertThat (annotatedBean .value ()).isEqualTo (2 );
91
+ }
92
+
93
+ @ Test
94
+ void testNoAnnotatedBeanInstance () {
95
+ AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext ();
96
+ parent .register (BaseConfig .class );
97
+ parent .refresh ();
98
+ TestClientFactory factory = new TestClientFactory ();
99
+ factory .setApplicationContext (parent );
100
+ factory .setConfigurations (List .of (getSpec ("not-annotated" , NotAnnotatedConfig .class )));
101
+
102
+ TestType annotatedBean = factory .getAnnotatedInstance ("not-annotated" , ResolvableType .forType (TestType .class ),
103
+ TestBean .class );
104
+ assertThat (annotatedBean ).isNull ();
105
+ }
106
+
107
+ @ Test
108
+ void testMoreThanOneAnnotatedBeanInstance () {
109
+ AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext ();
110
+ parent .register (BaseConfig .class );
111
+ parent .refresh ();
112
+ TestClientFactory factory = new TestClientFactory ();
113
+ factory .setApplicationContext (parent );
114
+ factory .setConfigurations (List .of (getSpec ("many-annotated" , ManyAnnotatedConfig .class )));
115
+
116
+ assertThatIllegalStateException ().isThrownBy (() -> factory .getAnnotatedInstance ("many-annotated" ,
117
+ ResolvableType .forType (TestType .class ), TestBean .class ));
118
+ }
119
+
53
120
private void testChildContexts (GenericApplicationContext parent ) {
54
121
TestClientFactory factory = new TestClientFactory ();
55
122
factory .setApplicationContext (parent );
@@ -97,7 +164,7 @@ private void testChildContexts(GenericApplicationContext parent) {
97
164
.as ("foo context bean factory classloader does not match parent" )
98
165
.isSameAs (parent .getBeanFactory ().getBeanClassLoader ());
99
166
100
- Assertions . assertThat (fooContext ).hasFieldOrPropertyWithValue ("customClassLoader" , true );
167
+ assertThat (fooContext ).hasFieldOrPropertyWithValue ("customClassLoader" , true );
101
168
102
169
factory .destroy ();
103
170
@@ -106,22 +173,6 @@ private void testChildContexts(GenericApplicationContext parent) {
106
173
then (barContext .isActive ()).as ("bar context wasn't closed" ).isFalse ();
107
174
}
108
175
109
- @ Test
110
- void testBadThreadContextClassLoader () throws InterruptedException , ExecutionException , TimeoutException {
111
- AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext ();
112
- parent .setClassLoader (ClassUtils .getDefaultClassLoader ());
113
- parent .register (BaseConfig .class );
114
- parent .refresh ();
115
-
116
- ExecutorService es = Executors .newSingleThreadExecutor (r -> {
117
- Thread t = new Thread (r );
118
- t .setContextClassLoader (new ThrowingClassLoader ());
119
- return t ;
120
- });
121
-
122
- es .submit (() -> this .testChildContexts (parent )).get (5 , TimeUnit .SECONDS );
123
- }
124
-
125
176
private TestSpec getSpec (String name , Class <?> configClass ) {
126
177
return new TestSpec (name , new Class [] { configClass });
127
178
}
@@ -236,18 +287,81 @@ static class Bar {
236
287
237
288
}
238
289
239
- static class Container <T > {
290
+ record Container <T > (T item ) {
291
+
292
+ }
293
+
294
+ static class AnnotatedConfig {
295
+
296
+ @ Bean
297
+ TestType test1 () {
298
+ return new TestType (1 );
299
+ }
240
300
241
- private final T item ;
301
+ @ TestBean
302
+ @ Bean
303
+ TestType test2 () {
304
+ return new TestType (2 );
305
+ }
242
306
243
- Container (T item ) {
244
- this .item = item ;
307
+ @ TestBean
308
+ @ Bean
309
+ Bar bar () {
310
+ return new Bar ();
245
311
}
246
312
247
- public T getItem () {
248
- return this .item ;
313
+ }
314
+
315
+ static class NotAnnotatedConfig {
316
+
317
+ @ Bean
318
+ TestType test1 () {
319
+ return new TestType (1 );
249
320
}
250
321
322
+ @ Bean
323
+ TestType test2 () {
324
+ return new TestType (2 );
325
+ }
326
+
327
+ @ TestBean
328
+ @ Bean
329
+ Bar bar () {
330
+ return new Bar ();
331
+ }
332
+
333
+ }
334
+
335
+ static class ManyAnnotatedConfig {
336
+
337
+ @ TestBean
338
+ @ Bean
339
+ TestType test1 () {
340
+ return new TestType (1 );
341
+ }
342
+
343
+ @ TestBean
344
+ @ Bean
345
+ TestType test2 () {
346
+ return new TestType (2 );
347
+ }
348
+
349
+ @ Bean
350
+ Bar bar () {
351
+ return new Bar ();
352
+ }
353
+
354
+ }
355
+
356
+ record TestType (int value ) {
357
+ }
358
+
359
+ @ Target ({ ElementType .TYPE , ElementType .METHOD })
360
+ @ Retention (RetentionPolicy .RUNTIME )
361
+ @ Documented
362
+ @ Inherited
363
+ @interface TestBean {
364
+
251
365
}
252
366
253
367
}
0 commit comments