1
1
/*
2
- * Copyright 2002-2024 the original author or authors.
2
+ * Copyright 2002-2025 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.
19
19
import org .junit .jupiter .api .Test ;
20
20
import org .junit .jupiter .api .Timeout ;
21
21
22
+ import org .springframework .beans .factory .BeanCurrentlyInCreationException ;
23
+ import org .springframework .beans .factory .ObjectProvider ;
22
24
import org .springframework .beans .testfixture .beans .TestBean ;
23
25
import org .springframework .context .ConfigurableApplicationContext ;
24
26
import org .springframework .core .testfixture .EnabledForTestGroups ;
25
27
import org .springframework .scheduling .concurrent .ThreadPoolTaskExecutor ;
26
28
29
+ import static org .assertj .core .api .Assertions .assertThatExceptionOfType ;
27
30
import static org .springframework .context .annotation .Bean .Bootstrap .BACKGROUND ;
28
31
import static org .springframework .core .testfixture .TestGroup .LONG_RUNNING ;
29
32
33
36
*/
34
37
class BackgroundBootstrapTests {
35
38
39
+ @ Test
40
+ @ Timeout (5 )
41
+ @ EnabledForTestGroups (LONG_RUNNING )
42
+ void bootstrapWithUnmanagedThread () {
43
+ ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext (UnmanagedThreadBeanConfig .class );
44
+ ctx .getBean ("testBean1" , TestBean .class );
45
+ assertThatExceptionOfType (BeanCurrentlyInCreationException .class ).isThrownBy ( // late - not during refresh
46
+ () -> ctx .getBean ("testBean2" , TestBean .class ));
47
+ ctx .close ();
48
+ }
49
+
36
50
@ Test
37
51
@ Timeout (5 )
38
52
@ EnabledForTestGroups (LONG_RUNNING )
@@ -45,7 +59,35 @@ void bootstrapWithCustomExecutor() {
45
59
}
46
60
47
61
48
- @ Configuration
62
+ @ Configuration (proxyBeanMethods = false )
63
+ static class UnmanagedThreadBeanConfig {
64
+
65
+ @ Bean
66
+ public TestBean testBean1 (ObjectProvider <TestBean > testBean2 ) {
67
+ new Thread (testBean2 ::getObject ).start ();
68
+ try {
69
+ Thread .sleep (1000 );
70
+ }
71
+ catch (InterruptedException ex ) {
72
+ throw new RuntimeException (ex );
73
+ }
74
+ return new TestBean ();
75
+ }
76
+
77
+ @ Bean
78
+ public TestBean testBean2 () {
79
+ try {
80
+ Thread .sleep (2000 );
81
+ }
82
+ catch (InterruptedException ex ) {
83
+ throw new RuntimeException (ex );
84
+ }
85
+ return new TestBean ();
86
+ }
87
+ }
88
+
89
+
90
+ @ Configuration (proxyBeanMethods = false )
49
91
static class CustomExecutorBeanConfig {
50
92
51
93
@ Bean
@@ -58,7 +100,7 @@ public ThreadPoolTaskExecutor bootstrapExecutor() {
58
100
}
59
101
60
102
@ Bean (bootstrap = BACKGROUND ) @ DependsOn ("testBean3" )
61
- public TestBean testBean1 (TestBean testBean3 ) throws InterruptedException {
103
+ public TestBean testBean1 (TestBean testBean3 ) throws InterruptedException {
62
104
Thread .sleep (3000 );
63
105
return new TestBean ();
64
106
}
0 commit comments