Skip to content

Commit 2d3c2e3

Browse files
committed
Revise contribution
See gh-35380
1 parent a41af44 commit 2d3c2e3

File tree

3 files changed

+63
-49
lines changed

3 files changed

+63
-49
lines changed

spring-core/src/main/java/org/springframework/util/function/SingletonSupplier.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class SingletonSupplier<T extends @Nullable Object> implements Supplier<T
4848
private volatile @Nullable T singletonInstance;
4949

5050
private volatile boolean initialized;
51+
5152
/**
5253
* Guards access to write operations on the {@code singletonInstance} field.
5354
*/
@@ -97,24 +98,27 @@ private SingletonSupplier(@Nullable T singletonInstance) {
9798
*/
9899
@Override
99100
public @Nullable T get() {
101+
T instance = this.singletonInstance;
100102
if (!this.initialized) {
101103
this.writeLock.lock();
102104
try {
105+
instance = this.singletonInstance;
103106
if (!this.initialized) {
104107
if (this.instanceSupplier != null) {
105-
this.singletonInstance = this.instanceSupplier.get();
108+
instance = this.instanceSupplier.get();
106109
}
107-
if (this.singletonInstance == null && this.defaultSupplier != null) {
108-
this.singletonInstance = this.defaultSupplier.get();
110+
if (instance == null && this.defaultSupplier != null) {
111+
instance = this.defaultSupplier.get();
109112
}
113+
this.singletonInstance = instance;
110114
this.initialized = true;
111115
}
112116
}
113117
finally {
114118
this.writeLock.unlock();
115119
}
116120
}
117-
return this.singletonInstance;
121+
return instance;
118122
}
119123

120124
/**

spring-core/src/test/java/org/springframework/util/function/SingletonSupplierTests.java

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
package org.springframework.util.function;
1818

1919
import java.util.ArrayList;
20-
import java.util.List;
2120
import java.util.concurrent.CountDownLatch;
22-
import java.util.concurrent.ExecutorService;
2321
import java.util.concurrent.Executors;
2422
import java.util.concurrent.Future;
2523
import java.util.concurrent.atomic.AtomicInteger;
@@ -29,123 +27,129 @@
2927
import org.junit.jupiter.api.Test;
3028

3129
import static org.assertj.core.api.Assertions.assertThat;
32-
import static org.assertj.core.api.Assertions.assertThatThrownBy;
30+
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
3331

3432
/**
3533
* Tests for {@link SingletonSupplier}.
3634
*
3735
* @author Dmytro Nosan
36+
* @author Sam Brannen
37+
* @since 7.0
3838
*/
3939
class SingletonSupplierTests {
4040

4141
@Test
4242
void shouldReturnDefaultWhenInstanceSupplierReturnsNull() {
43-
SingletonSupplier<String> singletonSupplier = new SingletonSupplier<>(() -> null, () -> "Default");
43+
var singletonSupplier = new SingletonSupplier<>(() -> null, () -> "Default");
44+
4445
assertThat(singletonSupplier.get()).isEqualTo("Default");
4546
}
4647

4748
@Test
4849
void shouldReturnNullForOfNullableWithNullInstance() {
49-
SingletonSupplier<String> singletonSupplier = SingletonSupplier.ofNullable((String) null);
50+
var singletonSupplier = SingletonSupplier.ofNullable((String) null);
51+
5052
assertThat(singletonSupplier).isNull();
5153
}
5254

5355
@Test
5456
void shouldReturnNullForOfNullableWithNullSupplier() {
55-
SingletonSupplier<String> singletonSupplier = SingletonSupplier.ofNullable((Supplier<String>) null);
57+
var singletonSupplier = SingletonSupplier.ofNullable((Supplier<String>) null);
58+
5659
assertThat(singletonSupplier).isNull();
5760
}
5861

5962
@Test
6063
void shouldReturnNullWhenAllSuppliersReturnNull() {
61-
SingletonSupplier<String> singletonSupplier = new SingletonSupplier<>(() -> null, () -> null);
64+
var singletonSupplier = new SingletonSupplier<>(() -> null, () -> null);
65+
6266
assertThat(singletonSupplier.get()).isNull();
6367
}
6468

6569
@Test
6670
void shouldReturnNullWhenNoInstanceOrDefaultSupplier() {
67-
SingletonSupplier<String> singletonSupplier = new SingletonSupplier<>((String) null, null);
71+
var singletonSupplier = new SingletonSupplier<>((String) null, null);
72+
6873
assertThat(singletonSupplier.get()).isNull();
6974
}
7075

7176
@Test
7277
void shouldReturnSingletonInstanceOnMultipleCalls() {
73-
SingletonSupplier<String> singletonSupplier = SingletonSupplier.of("Hello");
78+
var singletonSupplier = SingletonSupplier.of("Hello");
79+
7480
assertThat(singletonSupplier.get()).isEqualTo("Hello");
7581
assertThat(singletonSupplier.get()).isEqualTo("Hello");
7682
}
7783

78-
7984
@Test
8085
void shouldReturnSingletonInstanceOnMultipleSupplierCalls() {
81-
SingletonSupplier<String> singletonSupplier = SingletonSupplier.of(new HelloStringSupplier());
86+
var singletonSupplier = SingletonSupplier.of(new HelloStringSupplier());
87+
8288
assertThat(singletonSupplier.get()).isEqualTo("Hello 0");
8389
assertThat(singletonSupplier.get()).isEqualTo("Hello 0");
8490
}
8591

8692
@Test
8793
void shouldReturnSupplierForOfNullableWithNonNullInstance() {
88-
SingletonSupplier<String> singletonSupplier = SingletonSupplier.ofNullable("Hello");
94+
var singletonSupplier = SingletonSupplier.ofNullable("Hello");
95+
8996
assertThat(singletonSupplier).isNotNull();
9097
assertThat(singletonSupplier.get()).isEqualTo("Hello");
9198
}
9299

93100
@Test
94101
void shouldReturnSupplierForOfNullableWithNonNullSupplier() {
95-
SingletonSupplier<String> singletonSupplier = SingletonSupplier.ofNullable(() -> "Hello");
102+
var singletonSupplier = SingletonSupplier.ofNullable(() -> "Hello");
103+
96104
assertThat(singletonSupplier).isNotNull();
97105
assertThat(singletonSupplier.get()).isEqualTo("Hello");
98106
}
99107

100108
@Test
101109
void shouldThrowWhenObtainCalledAndNoInstanceAvailable() {
102-
SingletonSupplier<String> singletonSupplier = new SingletonSupplier<>((String) null, null);
103-
assertThatThrownBy(singletonSupplier::obtain).isInstanceOf(IllegalStateException.class)
104-
.hasMessage("No instance from Supplier");
110+
var singletonSupplier = new SingletonSupplier<>((String) null, null);
111+
112+
assertThatIllegalStateException()
113+
.isThrownBy(singletonSupplier::obtain)
114+
.withMessage("No instance from Supplier");
105115
}
106116

107117
@Test
108118
void shouldUseDefaultSupplierWhenInstanceIsNull() {
109-
SingletonSupplier<String> singletonSupplier = new SingletonSupplier<>((String) null, () -> "defaultSupplier");
119+
var singletonSupplier = new SingletonSupplier<>((String) null, () -> "defaultSupplier");
120+
110121
assertThat(singletonSupplier.get()).isEqualTo("defaultSupplier");
111122
}
112123

113124
@Test
114125
void shouldUseDefaultSupplierWhenInstanceSupplierReturnsNull() {
115-
SingletonSupplier<String> singletonSupplier = new SingletonSupplier<>((Supplier<String>) null, () -> "defaultSupplier");
126+
var singletonSupplier = new SingletonSupplier<>((Supplier<String>) null, () -> "defaultSupplier");
127+
116128
assertThat(singletonSupplier.get()).isEqualTo("defaultSupplier");
117129
}
118130

119131
@Test
120132
void shouldUseInstanceSupplierWhenProvidedAndIgnoreDefaultSupplier() {
121-
AtomicInteger defaultValue = new AtomicInteger();
122-
SingletonSupplier<Integer> singletonSupplier = new SingletonSupplier<>(() -> -1, defaultValue::incrementAndGet);
133+
var defaultValue = new AtomicInteger();
134+
var singletonSupplier = new SingletonSupplier<>(() -> -1, defaultValue::incrementAndGet);
135+
123136
assertThat(singletonSupplier.get()).isEqualTo(-1);
124-
assertThat(defaultValue.get()).isEqualTo(0);
137+
assertThat(defaultValue.get()).isZero();
125138
}
126139

127140
@Test
128141
void shouldUseInstanceWhenProvidedAndIgnoreDefaultSupplier() {
129-
AtomicInteger defaultValue = new AtomicInteger();
130-
SingletonSupplier<Integer> singletonSupplier = new SingletonSupplier<>(-1, defaultValue::incrementAndGet);
142+
var defaultValue = new AtomicInteger();
143+
var singletonSupplier = new SingletonSupplier<>(-1, defaultValue::incrementAndGet);
144+
131145
assertThat(singletonSupplier.get()).isEqualTo(-1);
132-
assertThat(defaultValue.get()).isEqualTo(0);
146+
assertThat(defaultValue.get()).isZero();
133147
}
134148

135149
@Test
136150
void shouldReturnConsistentlyNullSingletonInstanceOnMultipleSupplierCalls() {
137-
SingletonSupplier<String> singletonSupplier = SingletonSupplier.of(new Supplier<>() {
138-
139-
int count = 0;
140-
141-
@Override
142-
public String get() {
143-
if (this.count++ == 0) {
144-
return null;
145-
}
146-
return "Hello";
147-
}
148-
});
151+
var count = new AtomicInteger();
152+
var singletonSupplier = SingletonSupplier.of(() -> (count.getAndIncrement() == 0 ? null : "Hello"));
149153

150154
assertThat(singletonSupplier.get()).isNull();
151155
assertThat(singletonSupplier.get()).isNull();
@@ -154,11 +158,12 @@ public String get() {
154158
@RepeatedTest(100)
155159
void shouldReturnSingletonInstanceOnMultipleConcurrentSupplierCalls() throws Exception {
156160
int numberOfThreads = 4;
157-
CountDownLatch ready = new CountDownLatch(numberOfThreads);
158-
CountDownLatch start = new CountDownLatch(1);
159-
List<Future<String>> futures = new ArrayList<>();
160-
SingletonSupplier<String> singletonSupplier = SingletonSupplier.of(new HelloStringSupplier());
161-
ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
161+
var ready = new CountDownLatch(numberOfThreads);
162+
var start = new CountDownLatch(1);
163+
var futures = new ArrayList<Future<String>>();
164+
var singletonSupplier = SingletonSupplier.of(new HelloStringSupplier());
165+
var executorService = Executors.newFixedThreadPool(numberOfThreads);
166+
162167
try {
163168
for (int i = 0; i < numberOfThreads; i++) {
164169
futures.add(executorService.submit(() -> {
@@ -179,7 +184,7 @@ void shouldReturnSingletonInstanceOnMultipleConcurrentSupplierCalls() throws Exc
179184

180185
private static final class HelloStringSupplier implements Supplier<String> {
181186

182-
private final AtomicInteger count = new AtomicInteger();
187+
final AtomicInteger count = new AtomicInteger();
183188

184189
@Override
185190
public String get() {

spring-jdbc/src/test/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslatorTests.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
4040
import static org.mockito.BDDMockito.given;
4141
import static org.mockito.Mockito.mock;
42-
import static org.mockito.Mockito.reset;
4342
import static org.mockito.Mockito.verify;
4443

4544
/**
@@ -191,7 +190,7 @@ void customExceptionTranslation() {
191190
}
192191

193192
@Test
194-
void dataSourceInitialization() throws Exception {
193+
void dataSourceInitializationWhenConnectionCannotBeObtained() throws Exception {
195194
SQLException connectionException = new SQLException();
196195
SQLException duplicateKeyException = new SQLException("test", "", 1);
197196

@@ -200,15 +199,21 @@ void dataSourceInitialization() throws Exception {
200199

201200
translator = new SQLErrorCodeSQLExceptionTranslator(dataSource);
202201
assertThat(translator.translate("test", null, duplicateKeyException)).isNull();
202+
}
203+
204+
@Test
205+
void dataSourceInitialization() throws Exception {
206+
SQLException duplicateKeyException = new SQLException("test", "", 1);
203207

204208
DatabaseMetaData databaseMetaData = mock();
205209
given(databaseMetaData.getDatabaseProductName()).willReturn("Oracle");
206210

207211
Connection connection = mock();
208212
given(connection.getMetaData()).willReturn(databaseMetaData);
209213

210-
reset(dataSource);
214+
DataSource dataSource = mock();
211215
given(dataSource.getConnection()).willReturn(connection);
216+
212217
translator = new SQLErrorCodeSQLExceptionTranslator(dataSource);
213218
assertThat(translator.translate("test", null, duplicateKeyException))
214219
.isInstanceOf(DuplicateKeyException.class);

0 commit comments

Comments
 (0)