diff --git a/spring-context-indexer/src/main/java/org/springframework/context/index/processor/PropertiesMarshaller.java b/spring-context-indexer/src/main/java/org/springframework/context/index/processor/PropertiesMarshaller.java
index d1fdc09367..936591b548 100644
--- a/spring-context-indexer/src/main/java/org/springframework/context/index/processor/PropertiesMarshaller.java
+++ b/spring-context-indexer/src/main/java/org/springframework/context/index/processor/PropertiesMarshaller.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ import java.util.Set;
abstract class PropertiesMarshaller {
public static void write(CandidateComponentsMetadata metadata, OutputStream out) throws IOException {
- Properties props = new Properties();
+ Properties props = new SortedProperties(true);
metadata.getItems().forEach(m -> props.put(m.getType(), String.join(",", m.getStereotypes())));
props.store(out, "");
}
diff --git a/spring-context-indexer/src/main/java/org/springframework/context/index/processor/SortedProperties.java b/spring-context-indexer/src/main/java/org/springframework/context/index/processor/SortedProperties.java
new file mode 100644
index 0000000000..412e2bfb6b
--- /dev/null
+++ b/spring-context-indexer/src/main/java/org/springframework/context/index/processor/SortedProperties.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2002-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.context.index.processor;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Specialization of {@link Properties} that sorts properties alphanumerically
+ * based on their keys.
+ *
+ *
This can be useful when storing the {@link Properties} instance in a
+ * properties file, since it allows such files to be generated in a repeatable
+ * manner with consistent ordering of properties.
+ *
+ *
Comments in generated properties files can also be optionally omitted.
+ *
+ * @author Sam Brannen
+ * @since 5.2
+ * @see java.util.Properties
+ */
+@SuppressWarnings("serial")
+class SortedProperties extends Properties {
+
+ static final String EOL = System.lineSeparator();
+
+ private static final Comparator