19
19
import org .junit .jupiter .api .Test ;
20
20
import org .junit .jupiter .api .Timeout ;
21
21
22
+ import org .springframework .beans .factory .BeanCreationException ;
22
23
import org .springframework .beans .factory .BeanCurrentlyInCreationException ;
23
24
import org .springframework .beans .factory .ObjectProvider ;
24
25
import org .springframework .beans .factory .UnsatisfiedDependencyException ;
42
43
class BackgroundBootstrapTests {
43
44
44
45
@ Test
45
- @ Timeout (5 )
46
+ @ Timeout (10 )
46
47
@ EnabledForTestGroups (LONG_RUNNING )
47
48
void bootstrapWithUnmanagedThread () {
48
49
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext (UnmanagedThreadBeanConfig .class );
@@ -52,7 +53,7 @@ void bootstrapWithUnmanagedThread() {
52
53
}
53
54
54
55
@ Test
55
- @ Timeout (5 )
56
+ @ Timeout (10 )
56
57
@ EnabledForTestGroups (LONG_RUNNING )
57
58
void bootstrapWithUnmanagedThreads () {
58
59
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext (UnmanagedThreadsBeanConfig .class );
@@ -64,7 +65,7 @@ void bootstrapWithUnmanagedThreads() {
64
65
}
65
66
66
67
@ Test
67
- @ Timeout (5 )
68
+ @ Timeout (10 )
68
69
@ EnabledForTestGroups (LONG_RUNNING )
69
70
void bootstrapWithStrictLockingThread () {
70
71
SpringProperties .setFlag (DefaultListableBeanFactory .STRICT_LOCKING_PROPERTY_NAME );
@@ -79,17 +80,26 @@ void bootstrapWithStrictLockingThread() {
79
80
}
80
81
81
82
@ Test
82
- @ Timeout (5 )
83
+ @ Timeout (10 )
83
84
@ EnabledForTestGroups (LONG_RUNNING )
84
- void bootstrapWithCircularReference () {
85
- ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext (CircularReferenceBeanConfig .class );
85
+ void bootstrapWithCircularReferenceAgainstMainThread () {
86
+ ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext (CircularReferenceAgainstMainThreadBeanConfig .class );
86
87
ctx .getBean ("testBean1" , TestBean .class );
87
88
ctx .getBean ("testBean2" , TestBean .class );
88
89
ctx .close ();
89
90
}
90
91
91
92
@ Test
92
- @ Timeout (5 )
93
+ @ Timeout (10 )
94
+ @ EnabledForTestGroups (LONG_RUNNING )
95
+ void bootstrapWithCircularReferenceWithBlockingMainThread () {
96
+ assertThatExceptionOfType (BeanCreationException .class )
97
+ .isThrownBy (() -> new AnnotationConfigApplicationContext (CircularReferenceWithBlockingMainThreadBeanConfig .class ))
98
+ .withRootCauseInstanceOf (BeanCurrentlyInCreationException .class );
99
+ }
100
+
101
+ @ Test
102
+ @ Timeout (10 )
93
103
@ EnabledForTestGroups (LONG_RUNNING )
94
104
void bootstrapWithCircularReferenceInSameThread () {
95
105
assertThatExceptionOfType (UnsatisfiedDependencyException .class )
@@ -98,7 +108,16 @@ void bootstrapWithCircularReferenceInSameThread() {
98
108
}
99
109
100
110
@ Test
101
- @ Timeout (5 )
111
+ @ Timeout (10 )
112
+ @ EnabledForTestGroups (LONG_RUNNING )
113
+ void bootstrapWithCircularReferenceInMultipleThreads () {
114
+ assertThatExceptionOfType (BeanCreationException .class )
115
+ .isThrownBy (() -> new AnnotationConfigApplicationContext (CircularReferenceInMultipleThreadsBeanConfig .class ))
116
+ .withRootCauseInstanceOf (BeanCurrentlyInCreationException .class );
117
+ }
118
+
119
+ @ Test
120
+ @ Timeout (10 )
102
121
@ EnabledForTestGroups (LONG_RUNNING )
103
122
void bootstrapWithCustomExecutor () {
104
123
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext (CustomExecutorBeanConfig .class );
@@ -202,7 +221,7 @@ public TestBean testBean2(ConfigurableListableBeanFactory beanFactory) {
202
221
203
222
204
223
@ Configuration (proxyBeanMethods = false )
205
- static class CircularReferenceBeanConfig {
224
+ static class CircularReferenceAgainstMainThreadBeanConfig {
206
225
207
226
@ Bean
208
227
public TestBean testBean1 (ObjectProvider <TestBean > testBean2 ) {
@@ -229,6 +248,46 @@ public TestBean testBean2(TestBean testBean1) {
229
248
}
230
249
231
250
251
+ @ Configuration (proxyBeanMethods = false )
252
+ static class CircularReferenceWithBlockingMainThreadBeanConfig {
253
+
254
+ @ Bean
255
+ public TestBean testBean1 (ObjectProvider <TestBean > testBean2 ) {
256
+ Thread thread = new Thread (testBean2 ::getObject );
257
+ thread .setUncaughtExceptionHandler ((t , ex ) -> System .out .println (System .currentTimeMillis () + " " + ex + " " + t ));
258
+ thread .start ();
259
+ try {
260
+ Thread .sleep (1000 );
261
+ }
262
+ catch (InterruptedException ex ) {
263
+ throw new RuntimeException (ex );
264
+ }
265
+ return new TestBean (testBean2 .getObject ());
266
+ }
267
+
268
+ @ Bean
269
+ public TestBean testBean2 (ObjectProvider <TestBean > testBean1 ) {
270
+ System .out .println (System .currentTimeMillis () + " testBean2 begin " + Thread .currentThread ());
271
+ try {
272
+ Thread .sleep (2000 );
273
+ }
274
+ catch (InterruptedException ex ) {
275
+ throw new RuntimeException (ex );
276
+ }
277
+ try {
278
+ return new TestBean (testBean1 .getObject ());
279
+ }
280
+ catch (RuntimeException ex ) {
281
+ System .out .println (System .currentTimeMillis () + " testBean2 exception " + Thread .currentThread ());
282
+ throw ex ;
283
+ }
284
+ finally {
285
+ System .out .println (System .currentTimeMillis () + " testBean2 end " + Thread .currentThread ());
286
+ }
287
+ }
288
+ }
289
+
290
+
232
291
@ Configuration (proxyBeanMethods = false )
233
292
static class CircularReferenceInSameThreadBeanConfig {
234
293
@@ -262,6 +321,46 @@ public TestBean testBean3(TestBean testBean2) {
262
321
}
263
322
264
323
324
+ @ Configuration (proxyBeanMethods = false )
325
+ static class CircularReferenceInMultipleThreadsBeanConfig {
326
+
327
+ @ Bean
328
+ public TestBean testBean1 (ObjectProvider <TestBean > testBean2 , ObjectProvider <TestBean > testBean3 ) {
329
+ new Thread (testBean2 ::getObject ).start ();
330
+ new Thread (testBean3 ::getObject ).start ();
331
+ try {
332
+ Thread .sleep (2000 );
333
+ }
334
+ catch (InterruptedException ex ) {
335
+ throw new RuntimeException (ex );
336
+ }
337
+ return new TestBean ();
338
+ }
339
+
340
+ @ Bean
341
+ public TestBean testBean2 (ObjectProvider <TestBean > testBean3 ) {
342
+ try {
343
+ Thread .sleep (1000 );
344
+ }
345
+ catch (InterruptedException ex ) {
346
+ throw new RuntimeException (ex );
347
+ }
348
+ return new TestBean (testBean3 .getObject ());
349
+ }
350
+
351
+ @ Bean
352
+ public TestBean testBean3 (ObjectProvider <TestBean > testBean2 ) {
353
+ try {
354
+ Thread .sleep (1000 );
355
+ }
356
+ catch (InterruptedException ex ) {
357
+ throw new RuntimeException (ex );
358
+ }
359
+ return new TestBean (testBean2 .getObject ());
360
+ }
361
+ }
362
+
363
+
265
364
@ Configuration (proxyBeanMethods = false )
266
365
static class CustomExecutorBeanConfig {
267
366
0 commit comments