diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/spring-application.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/spring-application.adoc
index 52f7c34750b..fa2546775e7 100644
--- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/spring-application.adoc
+++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/spring-application.adoc
@@ -354,7 +354,8 @@ include::code:MyApplication[]
Also, the `ExitCodeGenerator` interface may be implemented by exceptions.
When such an exception is encountered, Spring Boot returns the exit code provided by the implemented `getExitCode()` method.
-
+If several `ExitCodeGenerator` are registered in a `ExitCodeGenerators`, they can be called in a specific order by using `org.springframework.core.annotation.Order` annotation or by implementing `org.springframework.core.Ordered`,
+and `ExitCodeGenerators#getExitCode()` will return the first non-zero value.
[[features.spring-application.admin]]
=== Admin Features
diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ExitCodeGenerators.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ExitCodeGenerators.java
index f26f16ea166..5fdbe92c661 100644
--- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ExitCodeGenerators.java
+++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ExitCodeGenerators.java
@@ -21,14 +21,22 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.AnnotationAwareOrderComparator;
+import org.springframework.core.annotation.Order;
import org.springframework.util.Assert;
/**
* Maintains a collection of {@link ExitCodeGenerator} instances and allows the final exit
* code to be calculated.
*
+ *
If several {@code ExitCodeGenerator} are registered in {@code ExitCodeGenerators},
+ * they can be called in a specific order by using {@link Order @Order} or by implementing {@link Ordered},
+ * and {@link #getExitCode()} will return the first non-zero value.
+ *
* @author Dave Syer
* @author Phillip Webb
+ * @author GenKui Du
* @see #getExitCode()
* @see ExitCodeGenerator
*/
@@ -84,15 +92,17 @@ class ExitCodeGenerators implements Iterable {
*/
int getExitCode() {
int exitCode = 0;
+ AnnotationAwareOrderComparator.sort(this.generators);
for (ExitCodeGenerator generator : this.generators) {
try {
int value = generator.getExitCode();
- if (value > 0 && value > exitCode || value < 0 && value < exitCode) {
+ if (value != 0) {
exitCode = value;
+ break;
}
}
catch (Exception ex) {
- exitCode = (exitCode != 0) ? exitCode : 1;
+ exitCode = 1;
ex.printStackTrace();
}
}
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ExitCodeGeneratorsTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ExitCodeGeneratorsTests.java
index 9a81e716265..e6252fa7572 100644
--- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ExitCodeGeneratorsTests.java
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ExitCodeGeneratorsTests.java
@@ -20,11 +20,13 @@ import java.io.IOException;
import java.util.List;
import org.junit.jupiter.api.Test;
+import org.springframework.core.Ordered;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
/**
* Tests for {@link ExitCodeGenerators}.
@@ -89,12 +91,29 @@ class ExitCodeGeneratorsTests {
assertThat(generators.getExitCode()).isEqualTo(2);
}
+ @Test
+ void getExitCodeWithOrderedGenerator() {
+ ExitCodeGenerators generators = new ExitCodeGenerators();
+ generators.add(mockGenerator(0, 1));
+ generators.add(mockGenerator(1, 3));
+ generators.add(mockGenerator(2, 2));
+ generators.add(mockGenerator(3, 4));
+ assertThat(generators.getExitCode()).isEqualTo(2);
+ }
+
private ExitCodeGenerator mockGenerator(int exitCode) {
ExitCodeGenerator generator = mock(ExitCodeGenerator.class);
given(generator.getExitCode()).willReturn(exitCode);
return generator;
}
+ private ExitCodeGenerator mockGenerator(int exitCode, int orderValue) {
+ ExitCodeGenerator generator = mock(ExitCodeGenerator.class, withSettings().extraInterfaces(Ordered.class));
+ given(generator.getExitCode()).willReturn(exitCode);
+ given(((Ordered) generator).getOrder()).willReturn(orderValue);
+ return generator;
+ }
+
private ExitCodeExceptionMapper mockMapper(Class> exceptionType, int exitCode) {
return (exception) -> {
if (exceptionType.isInstance(exception)) {