Skip to content

Commit e52e26d

Browse files
authored
Reverse PreDestroy Order (#883)
* Reverse PreDestroy Order Now will execute same priority predestroy hooks in reverse order
1 parent e55a92e commit e52e26d

File tree

4 files changed

+92
-27
lines changed

4 files changed

+92
-27
lines changed

blackbox-test-inject/src/main/java/org/example/myapp/MyDestroyOrder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public class MyDestroyOrder {
88

99
private static final List<String> ordering = Collections.synchronizedList(new ArrayList<>());
1010

11-
public static void add(String val){
11+
public static void add(String val) {
1212
ordering.add(val);
1313
}
1414

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.example.myapp;
2+
3+
import io.avaje.inject.PreDestroy;
4+
import jakarta.inject.Singleton;
5+
6+
import java.util.ArrayList;
7+
import java.util.Collections;
8+
import java.util.List;
9+
10+
public class MyDestroyOrder2 {
11+
12+
private static final List<String> ordering = Collections.synchronizedList(new ArrayList<>());
13+
14+
public static void add(String val) {
15+
ordering.add(val);
16+
}
17+
18+
public static List<String> ordering() {
19+
return ordering;
20+
}
21+
22+
@Singleton
23+
public static class One {
24+
@PreDestroy
25+
public void close() {
26+
add("One");
27+
}
28+
}
29+
30+
@Singleton
31+
public static class Two {
32+
33+
final One one;
34+
35+
public Two(One one) {
36+
this.one = one;
37+
}
38+
39+
@PreDestroy
40+
public void close() {
41+
add("Two");
42+
}
43+
}
44+
45+
}

blackbox-test-inject/src/test/java/org/example/myapp/MyDestroyOrderTest.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,35 @@
33
import io.avaje.inject.BeanScope;
44
import org.junit.jupiter.api.Test;
55

6-
import java.util.List;
7-
86
import static org.assertj.core.api.Assertions.assertThat;
97

108
class MyDestroyOrderTest {
119

1210
@Test
13-
void ordering() {
11+
void ordering_byPriority() {
1412
MyDestroyOrder.ordering().clear();
1513
try (BeanScope beanScope = BeanScope.builder().build()) {
1614
beanScope.get(HelloService.class);
1715
}
18-
List<String> ordering = MyDestroyOrder.ordering();
19-
assertThat(ordering).containsExactly("HelloService", "AppConfig", "MyNamed", "MyMetaDataRepo", "ExampleService", "AppHelloData");
16+
assertThat(MyDestroyOrder.ordering())
17+
.containsExactly(
18+
"HelloService",
19+
"MyNamed",
20+
"AppConfig",
21+
"MyMetaDataRepo",
22+
"ExampleService",
23+
"AppHelloData");
24+
}
25+
26+
@Test
27+
void ordering_expect_reverseOfDependencies() {
28+
MyDestroyOrder2.ordering().clear();
29+
try (BeanScope beanScope = BeanScope.builder().build()) {
30+
beanScope.get(HelloService.class);
31+
}
32+
assertThat(MyDestroyOrder2.ordering())
33+
.containsExactly(
34+
"Two",
35+
"One");
2036
}
2137
}

inject/src/main/java/io/avaje/inject/spi/DBuilder.java

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
11
package io.avaje.inject.spi;
22

3-
import io.avaje.inject.BeanEntry;
4-
import io.avaje.inject.BeanScope;
5-
import jakarta.inject.Provider;
6-
import org.jspecify.annotations.Nullable;
3+
import static io.avaje.inject.spi.DBeanScope.combine;
74

85
import java.lang.reflect.Type;
9-
import java.util.*;
6+
import java.util.ArrayDeque;
7+
import java.util.ArrayList;
8+
import java.util.Arrays;
9+
import java.util.Collections;
10+
import java.util.Deque;
11+
import java.util.LinkedHashSet;
12+
import java.util.List;
13+
import java.util.Map;
14+
import java.util.Optional;
15+
import java.util.Set;
1016
import java.util.function.Consumer;
1117
import java.util.stream.Collectors;
1218

13-
import static io.avaje.inject.spi.DBeanScope.combine;
19+
import org.jspecify.annotations.Nullable;
20+
21+
import io.avaje.inject.BeanEntry;
22+
import io.avaje.inject.BeanScope;
23+
import jakarta.inject.Provider;
1424

1525
class DBuilder implements Builder {
1626

@@ -20,7 +30,8 @@ class DBuilder implements Builder {
2030
private final List<Runnable> postConstruct = new ArrayList<>();
2131

2232
private final List<Consumer<BeanScope>> postConstructConsumers = new ArrayList<>();
23-
private final List<ClosePair> preDestroy = new ArrayList<>();
33+
private final Deque<ClosePair> preDestroy = new ArrayDeque<>();
34+
2435
/** List of field injection closures. */
2536
private final List<Consumer<Builder>> injectors = new ArrayList<>();
2637
/** The beans created and added to the scope during building. */
@@ -226,13 +237,13 @@ public final void addPreDestroy(AutoCloseable invoke) {
226237

227238
@Override
228239
public final void addPreDestroy(AutoCloseable invoke, int priority) {
229-
preDestroy.add(new ClosePair(priority, invoke));
240+
preDestroy.addFirst(new ClosePair(priority, invoke));
230241
}
231242

232243
@Override
233244
public final void addAutoClosable(Object maybeAutoCloseable) {
234245
if (maybeAutoCloseable instanceof AutoCloseable) {
235-
preDestroy.add(new ClosePair(1000, (AutoCloseable) maybeAutoCloseable));
246+
preDestroy.addFirst(new ClosePair(1000, (AutoCloseable) maybeAutoCloseable));
236247
}
237248
}
238249

@@ -333,12 +344,7 @@ public final <T> Provider<T> getProviderFor(Class<?> cls, Type type) {
333344
if (bean != null) {
334345
return bean;
335346
}
336-
final String msg =
337-
"Unable to inject an instance for generic type "
338-
+ type
339-
+ " usually provided by "
340-
+ cls
341-
+ "?";
347+
final String msg = "Unable to inject an instance for generic type " + type + " usually provided by " + cls + "?";
342348
throw new IllegalStateException(msg);
343349
};
344350
}
@@ -378,12 +384,12 @@ public final boolean containsAllProfiles(List<String> type) {
378384

379385
@Override
380386
public final boolean contains(String type) {
381-
return beanMap.contains(type) || (parent != null && parent.contains(type));
387+
return beanMap.contains(type) || parent != null && parent.contains(type);
382388
}
383389

384390
@Override
385391
public final boolean contains(Type type) {
386-
return beanMap.contains(type) || (parent != null && parent.contains(type));
392+
return beanMap.contains(type) || parent != null && parent.contains(type);
387393
}
388394

389395
@Override
@@ -450,12 +456,10 @@ public final BeanScope build(boolean withShutdownHook, long start) {
450456
return scope.start(start);
451457
}
452458

453-
/**
454-
* Return the PreDestroy methods in priority order.
455-
*/
459+
/** Return the PreDestroy methods in priority order. */
456460
private List<AutoCloseable> preDestroy() {
457-
Collections.sort(preDestroy);
458461
return preDestroy.stream()
462+
.sorted()
459463
.map(ClosePair::closeable)
460464
.collect(Collectors.toList());
461465
}

0 commit comments

Comments
 (0)