@@ -218,8 +218,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
218
218
/** Whether bean definition metadata may be cached for all beans. */
219
219
private volatile boolean configurationFrozen ;
220
220
221
- private volatile boolean preInstantiationPhase ;
222
-
221
+ /** Name prefix of main thread: only set during pre-instantiation phase. */
223
222
@ Nullable
224
223
private volatile String mainThreadPrefix ;
225
224
@@ -1066,26 +1065,37 @@ protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName
1066
1065
@ Override
1067
1066
@ Nullable
1068
1067
protected Boolean isCurrentThreadAllowedToHoldSingletonLock () {
1069
- if (this .preInstantiationPhase ) {
1068
+ String mainThreadPrefix = this .mainThreadPrefix ;
1069
+ if (this .mainThreadPrefix != null ) {
1070
1070
// We only differentiate in the preInstantiateSingletons phase.
1071
+
1071
1072
PreInstantiation preInstantiation = this .preInstantiationThread .get ();
1072
1073
if (preInstantiation != null ) {
1073
- // A Spring-managed thread:
1074
+ // A Spring-managed bootstrap thread:
1074
1075
// MAIN is allowed to lock (true) or even forced to lock (null),
1075
1076
// BACKGROUND is never allowed to lock (false).
1076
1077
return switch (preInstantiation ) {
1077
1078
case MAIN -> (Boolean .TRUE .equals (this .strictLocking ) ? null : true );
1078
1079
case BACKGROUND -> false ;
1079
1080
};
1080
1081
}
1081
- if (Boolean .FALSE .equals (this .strictLocking ) ||
1082
- (this .strictLocking == null && !getThreadNamePrefix ().equals (this .mainThreadPrefix ))) {
1083
- // An unmanaged thread (assumed to be application-internal) with lenient locking,
1084
- // and not part of the same thread pool that provided the main bootstrap thread
1085
- // (excluding scenarios where we are hit by multiple external bootstrap threads).
1082
+
1083
+ // Not a Spring-managed bootstrap thread...
1084
+ if (Boolean .FALSE .equals (this .strictLocking )) {
1085
+ // Explicitly configured to use lenient locking wherever possible.
1086
1086
return true ;
1087
1087
}
1088
+ else if (this .strictLocking == null ) {
1089
+ // No explicit locking configuration -> infer appropriate locking.
1090
+ if (mainThreadPrefix != null && !getThreadNamePrefix ().equals (mainThreadPrefix )) {
1091
+ // An unmanaged thread (assumed to be application-internal) with lenient locking,
1092
+ // and not part of the same thread pool that provided the main bootstrap thread
1093
+ // (excluding scenarios where we are hit by multiple external bootstrap threads).
1094
+ return true ;
1095
+ }
1096
+ }
1088
1097
}
1098
+
1089
1099
// Traditional behavior: forced to always hold a full lock.
1090
1100
return null ;
1091
1101
}
@@ -1103,7 +1113,6 @@ public void preInstantiateSingletons() throws BeansException {
1103
1113
// Trigger initialization of all non-lazy singleton beans...
1104
1114
List <CompletableFuture <?>> futures = new ArrayList <>();
1105
1115
1106
- this .preInstantiationPhase = true ;
1107
1116
this .preInstantiationThread .set (PreInstantiation .MAIN );
1108
1117
this .mainThreadPrefix = getThreadNamePrefix ();
1109
1118
try {
@@ -1120,7 +1129,6 @@ public void preInstantiateSingletons() throws BeansException {
1120
1129
finally {
1121
1130
this .mainThreadPrefix = null ;
1122
1131
this .preInstantiationThread .remove ();
1123
- this .preInstantiationPhase = false ;
1124
1132
}
1125
1133
1126
1134
if (!futures .isEmpty ()) {
0 commit comments