This is an automated email from the ASF dual-hosted git repository.
strongduanmu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 023477125a6 fix(spi): avoid retaining multi-object OrderedSPI cache
keys (#38980)
023477125a6 is described below
commit 023477125a6c14e5f5632a4d099245895c9acc3d
Author: Cong Hu <[email protected]>
AuthorDate: Thu Jul 2 16:14:28 2026 +0800
fix(spi): avoid retaining multi-object OrderedSPI cache keys (#38980)
* fix(spi): avoid retaining multi-object OrderedSPI cache keys
WHAT: Remove the singleton OrderedSPILoader object-collection cache for
multi-object lookups and add focused coverage for multi-object, same-class,
comparator, singleton, and prototype behavior.
WHY: Transient RuleConfiguration and YamlRuleConfiguration collections can
otherwise be retained by the JVM-lifetime singleton registry and lead to heap
growth, frequent Full GC, and OOM.
HOW: Keep the single-object fast path, singleton service reuse, and
class-based cache. Rebuild current object-keyed results from Class<?> keys for
multi-object lookups. Verified with infra/spi tests, Spotless, Checkstyle, RAT,
and local JMH before/after.
* docs: add release note for OrderedSPILoader cache fix
---
RELEASE-NOTES.md | 1 +
.../infra/spi/type/ordered/OrderedSPILoader.java | 25 ++--
.../spi/type/ordered/OrderedSPILoaderTest.java | 135 +++++++++++++++------
.../impl/ChildOrderedInterfaceFixtureImpl.java | 21 ++++
.../ComparableOrderedInterfaceFixtureImpl.java | 48 ++++++++
.../impl/ComparableOrderedSPIFixtureImpl.java | 33 +++++
...omparableOrderedSPINonSingletonFixtureImpl.java | 33 +++++
.../impl/ParentOrderedInterfaceFixtureImpl.java | 23 ++++
.../fixture/impl/ParentOrderedSPIFixtureImpl.java | 33 +++++
.../ParentOrderedSPINonSingletonFixtureImpl.java | 33 +++++
...nfra.spi.type.ordered.fixture.OrderedSPIFixture | 2 +
...e.ordered.fixture.OrderedSPINonSingletonFixture | 2 +
12 files changed, 335 insertions(+), 54 deletions(-)
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index d9e4224aa3f..bf53184ef33 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -24,6 +24,7 @@
1. Proxy: Reject unsupported MySQL and Doris temporary table DDL before
backend execution -
[#38829](https://github.com/apache/shardingsphere/pull/38829)
1. JDBC & Proxy: Remove default MySQL prepared statement query properties when
creating data sources -
[#38593](https://github.com/apache/shardingsphere/pull/38593)
1. Mode: Fix rule metadata not removed from memory after dropping rules in
Etcd cluster mode -
[#38561](https://github.com/apache/shardingsphere/pull/38561)
+1. Infra: Avoid retaining transient multi-object lookup keys in
`OrderedSPILoader` -
[#38980](https://github.com/apache/shardingsphere/pull/38980)
1. Pipeline: Fix MySQL JSON literal decoding in migration -
[#38622](https://github.com/apache/shardingsphere/pull/38622)
1. Pipeline: Fix MySQL zero-value temporal binlog decoding with fractional
precision in migration -
[#38629](https://github.com/apache/shardingsphere/pull/38629)
1. Pipeline: Fix escape MySQL JSON binlog control characters -
[#38800](https://github.com/apache/shardingsphere/pull/38800)
diff --git
a/infra/spi/src/main/java/org/apache/shardingsphere/infra/spi/type/ordered/OrderedSPILoader.java
b/infra/spi/src/main/java/org/apache/shardingsphere/infra/spi/type/ordered/OrderedSPILoader.java
index e58bcb819ac..961f92e802c 100644
---
a/infra/spi/src/main/java/org/apache/shardingsphere/infra/spi/type/ordered/OrderedSPILoader.java
+++
b/infra/spi/src/main/java/org/apache/shardingsphere/infra/spi/type/ordered/OrderedSPILoader.java
@@ -129,8 +129,6 @@ public final class OrderedSPILoader {
private final Map<Set<Class<?>>, Map<Class<?>, T>>
multiTypeClassToServices = new ConcurrentHashMap<>();
- private final Map<Collection<?>, Map<?, T>> multiObjectToServices =
new ConcurrentHashMap<>();
-
@SuppressWarnings({"rawtypes", "unchecked"})
CachedSingletonOrderedSPIRegistry(final Class<?> serviceInterface) {
Map<Integer, T> orderServices = new
TreeMap<>(Comparator.naturalOrder());
@@ -177,33 +175,26 @@ public final class OrderedSPILoader {
}
@Override
- @SuppressWarnings("unchecked")
public <K> Map<K, T> getServices(final Collection<K> types) {
if (1 == types.size()) {
K type = types.iterator().next();
T service = singleTypeClassToService.get(type.getClass());
return null == service ? Collections.emptyMap() :
Collections.singletonMap(type, service);
}
- Map<?, T> result = multiObjectToServices.get(types);
- if (null == result) {
- result = multiObjectToServices.computeIfAbsent(types, t ->
computeServicesByObject((Collection<Object>) t));
- }
- return (Map<K, T>) result;
+ return computeServicesByObject(types);
}
- private Map<Object, T> computeServicesByObject(final
Collection<Object> types) {
- Map<Class<?>, List<Object>> classTypeMap = new
HashMap<>(types.size(), 1F);
+ private <K> Map<K, T> computeServicesByObject(final Collection<K>
types) {
+ Map<Class<?>, List<K>> classTypeMap = new HashMap<>(types.size(),
1F);
Set<Class<?>> typeClasses = new HashSet<>(types.size(), 1F);
- for (Object each : types) {
+ for (K each : types) {
classTypeMap.computeIfAbsent(each.getClass(), clazz -> new
LinkedList<>()).add(each);
typeClasses.add(each.getClass());
}
- Map<Object, T> result = new LinkedHashMap<>(types.size(), 1F);
- for (T each : orderedServices) {
- if (typeClasses.contains(each.getTypeClass())) {
- for (Object type : classTypeMap.get(each.getTypeClass())) {
- result.put(type, each);
- }
+ Map<K, T> result = new LinkedHashMap<>(types.size(), 1F);
+ for (T each : getServicesByClass(typeClasses).values()) {
+ for (K type : classTypeMap.get(each.getTypeClass())) {
+ result.put(type, each);
}
}
return result;
diff --git
a/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/OrderedSPILoaderTest.java
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/OrderedSPILoaderTest.java
index 3d90c523bb4..89480eae018 100644
---
a/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/OrderedSPILoaderTest.java
+++
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/OrderedSPILoaderTest.java
@@ -17,46 +17,70 @@
package org.apache.shardingsphere.infra.spi.type.ordered;
-import
org.apache.shardingsphere.infra.spi.type.ordered.cache.OrderedServicesCache;
import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedInterfaceFixture;
import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPIFixture;
import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPINonSingletonFixture;
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.ChildOrderedInterfaceFixtureImpl;
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.ComparableOrderedInterfaceFixtureImpl;
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.ComparableOrderedSPIFixtureImpl;
import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.OrderedInterfaceFixtureImpl;
import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.OrderedSPIFixtureImpl;
-import org.junit.jupiter.api.AfterEach;
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.ParentOrderedInterfaceFixtureImpl;
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.ParentOrderedSPIFixtureImpl;
import org.junit.jupiter.api.Test;
-import org.mockito.internal.configuration.plugins.Plugins;
-import java.lang.ref.SoftReference;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedList;
import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isA;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.sameInstance;
+@SuppressWarnings("rawtypes")
class OrderedSPILoaderTest {
- @SuppressWarnings("CollectionWithoutInitialCapacity")
- @AfterEach
- void cleanCache() throws ReflectiveOperationException {
-
Plugins.getMemberAccessor().set(OrderedServicesCache.class.getDeclaredField("cache"),
OrderedServicesCache.class, new SoftReference<>(new ConcurrentHashMap<>()));
+ @Test
+ void assertGetOrderedServices() {
+ Collection<Class<?>> actualClasses = new LinkedList<>();
+ for (OrderedSPIFixture each :
OrderedSPILoader.getServices(OrderedSPIFixture.class)) {
+ actualClasses.add(each.getClass());
+ }
+ assertThat(actualClasses, contains(ParentOrderedSPIFixtureImpl.class,
OrderedSPIFixtureImpl.class, ComparableOrderedSPIFixtureImpl.class));
}
- @SuppressWarnings("rawtypes")
@Test
- void assertGetServicesByClass() {
+ void assertGetServicesByClassWithSingleClass() {
Map<Class<?>, OrderedSPIFixture> actual =
OrderedSPILoader.getServicesByClass(OrderedSPIFixture.class,
Collections.singleton(OrderedInterfaceFixtureImpl.class));
assertThat(actual.size(), is(1));
assertThat(actual.get(OrderedInterfaceFixtureImpl.class),
isA(OrderedSPIFixtureImpl.class));
}
- @SuppressWarnings("rawtypes")
@Test
- void assertGetServices() {
+ void assertGetServicesByClassWithMultiClass() {
+ Map<Class<?>, OrderedSPIFixture> actual =
OrderedSPILoader.getServicesByClass(OrderedSPIFixture.class,
+ Arrays.<Class<?>>asList(OrderedInterfaceFixtureImpl.class,
ParentOrderedInterfaceFixtureImpl.class));
+ assertThat(actual.keySet(),
contains(ParentOrderedInterfaceFixtureImpl.class,
OrderedInterfaceFixtureImpl.class));
+ }
+
+ @Test
+ void assertGetServicesByClassWithEmptyClass() {
+
assertThat(OrderedSPILoader.getServicesByClass(OrderedSPIFixture.class,
Collections.<Class<?>>emptyList()).entrySet(), empty());
+ }
+
+ @Test
+ void assertGetServicesByClassWithNoMatchClass() {
+
assertThat(OrderedSPILoader.getServicesByClass(OrderedSPIFixture.class,
Collections.<Class<?>>singleton(ChildOrderedInterfaceFixtureImpl.class)).entrySet(),
empty());
+ }
+
+ @Test
+ void assertGetServicesWithSingleObject() {
OrderedInterfaceFixtureImpl key = new OrderedInterfaceFixtureImpl();
Map<OrderedInterfaceFixtureImpl, OrderedSPIFixture> actual =
OrderedSPILoader.getServices(OrderedSPIFixture.class,
Collections.singleton(key));
assertThat(actual.size(), is(1));
@@ -64,43 +88,80 @@ class OrderedSPILoaderTest {
}
@Test
- void assertGetServicesFromCache() {
- OrderedInterfaceFixture key = new OrderedInterfaceFixtureImpl();
- assertThat(OrderedSPILoader.getServices(OrderedSPIFixture.class,
Collections.singleton(key)),
- is(OrderedSPILoader.getServices(OrderedSPIFixture.class,
Collections.singleton(key))));
+ void assertGetServicesWithMultiObject() {
+ OrderedInterfaceFixtureImpl orderedKey = new
OrderedInterfaceFixtureImpl();
+ ParentOrderedInterfaceFixtureImpl parentKey = new
ParentOrderedInterfaceFixtureImpl();
+ Map<OrderedInterfaceFixture, OrderedSPIFixture> actual =
OrderedSPILoader.getServices(OrderedSPIFixture.class,
Arrays.<OrderedInterfaceFixture>asList(orderedKey, parentKey));
+ assertThat(actual.keySet(), contains(parentKey, orderedKey));
+ }
+
+ @Test
+ void assertGetServicesWithEmptyObject() {
+ assertThat(OrderedSPILoader.getServices(OrderedSPIFixture.class,
Collections.<OrderedInterfaceFixture>emptyList()).entrySet(), empty());
+ }
+
+ @Test
+ void assertGetServicesWithExactRuntimeClass() {
+ Map<OrderedInterfaceFixture, OrderedSPIFixture> actual =
OrderedSPILoader.getServices(OrderedSPIFixture.class,
+ Collections.<OrderedInterfaceFixture>singleton(new
ChildOrderedInterfaceFixtureImpl()));
+ assertThat(actual.entrySet(), empty());
+ }
+
+ @Test
+ void assertGetServicesWithSameClassObjects() {
+ ComparableOrderedInterfaceFixtureImpl firstKey = new
ComparableOrderedInterfaceFixtureImpl("foo_same_1");
+ ComparableOrderedInterfaceFixtureImpl secondKey = new
ComparableOrderedInterfaceFixtureImpl("foo_same_2");
+ Map<OrderedInterfaceFixture, OrderedSPIFixture> actual =
OrderedSPILoader.getServices(OrderedSPIFixture.class,
Arrays.<OrderedInterfaceFixture>asList(firstKey, secondKey));
+ assertThat(actual.keySet(), contains(firstKey, secondKey));
+ }
+
+ @Test
+ void assertGetServicesWithCurrentObjectKeys() {
+ OrderedSPILoader.getServices(OrderedSPIFixture.class,
Arrays.<OrderedInterfaceFixture>asList(new
ComparableOrderedInterfaceFixtureImpl("foo_equal_1"),
+ new ComparableOrderedInterfaceFixtureImpl("foo_equal_2")));
+ ComparableOrderedInterfaceFixtureImpl firstKey = new
ComparableOrderedInterfaceFixtureImpl("foo_equal_1");
+ ComparableOrderedInterfaceFixtureImpl secondKey = new
ComparableOrderedInterfaceFixtureImpl("foo_equal_2");
+ Map<OrderedInterfaceFixture, OrderedSPIFixture> actual =
OrderedSPILoader.getServices(OrderedSPIFixture.class,
Arrays.<OrderedInterfaceFixture>asList(firstKey, secondKey));
+ assertThat(actual.keySet(), contains(sameInstance(firstKey),
sameInstance(secondKey)));
+ }
+
+ @Test
+ void assertGetServicesByComparator() {
+ OrderedInterfaceFixtureImpl orderedKey = new
OrderedInterfaceFixtureImpl();
+ ParentOrderedInterfaceFixtureImpl parentKey = new
ParentOrderedInterfaceFixtureImpl();
+ ComparableOrderedInterfaceFixtureImpl comparableKey = new
ComparableOrderedInterfaceFixtureImpl("foo_comparator");
+ Map<OrderedInterfaceFixture, OrderedSPIFixture> actual =
OrderedSPILoader.getServices(OrderedSPIFixture.class,
+ Arrays.<OrderedInterfaceFixture>asList(parentKey, orderedKey,
comparableKey), Collections.<Integer>reverseOrder());
+ assertThat(actual.keySet(), contains(comparableKey, orderedKey,
parentKey));
}
- @SuppressWarnings("rawtypes")
@Test
- void assertGetServicesByClassWithSingletonSPIReturnsSameInstance() {
- Map<Class<?>, OrderedSPIFixture> firstCall =
OrderedSPILoader.getServicesByClass(OrderedSPIFixture.class,
Collections.singleton(OrderedInterfaceFixtureImpl.class));
- Map<Class<?>, OrderedSPIFixture> secondCall =
OrderedSPILoader.getServicesByClass(OrderedSPIFixture.class,
Collections.singleton(OrderedInterfaceFixtureImpl.class));
- assertThat(firstCall.get(OrderedInterfaceFixtureImpl.class),
is(sameInstance(secondCall.get(OrderedInterfaceFixtureImpl.class))));
+ void assertGetServicesByClassWithSingletonSPI() {
+ Map<Class<?>, OrderedSPIFixture> firstActual =
OrderedSPILoader.getServicesByClass(OrderedSPIFixture.class,
Collections.singleton(OrderedInterfaceFixtureImpl.class));
+ Map<Class<?>, OrderedSPIFixture> secondActual =
OrderedSPILoader.getServicesByClass(OrderedSPIFixture.class,
Collections.singleton(OrderedInterfaceFixtureImpl.class));
+ assertThat(firstActual.get(OrderedInterfaceFixtureImpl.class),
is(sameInstance(secondActual.get(OrderedInterfaceFixtureImpl.class))));
}
- @SuppressWarnings("rawtypes")
@Test
- void assertGetServicesWithSingletonSPIReturnsSameInstance() {
+ void assertGetServicesWithSingletonSPI() {
OrderedInterfaceFixtureImpl key = new OrderedInterfaceFixtureImpl();
- Map<OrderedInterfaceFixtureImpl, OrderedSPIFixture> firstCall =
OrderedSPILoader.getServices(OrderedSPIFixture.class,
Collections.singleton(key));
- Map<OrderedInterfaceFixtureImpl, OrderedSPIFixture> secondCall =
OrderedSPILoader.getServices(OrderedSPIFixture.class,
Collections.singleton(key));
- assertThat(firstCall.get(key), is(sameInstance(secondCall.get(key))));
+ Map<OrderedInterfaceFixtureImpl, OrderedSPIFixture> firstActual =
OrderedSPILoader.getServices(OrderedSPIFixture.class,
Collections.singleton(key));
+ Map<OrderedInterfaceFixtureImpl, OrderedSPIFixture> secondActual =
OrderedSPILoader.getServices(OrderedSPIFixture.class,
Collections.singleton(key));
+ assertThat(firstActual.get(key),
is(sameInstance(secondActual.get(key))));
}
- @SuppressWarnings("rawtypes")
@Test
- void
assertGetServicesByClassWithNonSingletonSPIReturnsDifferentInstances() {
- Map<Class<?>, OrderedSPINonSingletonFixture> firstCall =
OrderedSPILoader.getServicesByClass(OrderedSPINonSingletonFixture.class,
Collections.singleton(OrderedInterfaceFixtureImpl.class));
- Map<Class<?>, OrderedSPINonSingletonFixture> secondCall =
OrderedSPILoader.getServicesByClass(OrderedSPINonSingletonFixture.class,
Collections.singleton(OrderedInterfaceFixtureImpl.class));
- assertThat(firstCall.get(OrderedInterfaceFixtureImpl.class),
is(not(sameInstance(secondCall.get(OrderedInterfaceFixtureImpl.class)))));
+ void assertGetServicesByClassWithNonSingletonSPI() {
+ Map<Class<?>, OrderedSPINonSingletonFixture> firstActual =
OrderedSPILoader.getServicesByClass(OrderedSPINonSingletonFixture.class,
Collections.singleton(OrderedInterfaceFixtureImpl.class));
+ Map<Class<?>, OrderedSPINonSingletonFixture> secondActual =
OrderedSPILoader.getServicesByClass(OrderedSPINonSingletonFixture.class,
Collections.singleton(OrderedInterfaceFixtureImpl.class));
+ assertThat(firstActual.get(OrderedInterfaceFixtureImpl.class),
is(not(sameInstance(secondActual.get(OrderedInterfaceFixtureImpl.class)))));
}
- @SuppressWarnings("rawtypes")
@Test
- void assertGetServicesWithNonSingletonSPIReturnsDifferentInstances() {
+ void assertGetServicesWithNonSingletonSPI() {
OrderedInterfaceFixtureImpl key = new OrderedInterfaceFixtureImpl();
- Map<OrderedInterfaceFixtureImpl, OrderedSPINonSingletonFixture>
firstCall = OrderedSPILoader.getServices(OrderedSPINonSingletonFixture.class,
Collections.singleton(key));
- Map<OrderedInterfaceFixtureImpl, OrderedSPINonSingletonFixture>
secondCall = OrderedSPILoader.getServices(OrderedSPINonSingletonFixture.class,
Collections.singleton(key));
- assertThat(firstCall.get(key),
is(not(sameInstance(secondCall.get(key)))));
+ Map<OrderedInterfaceFixtureImpl, OrderedSPINonSingletonFixture>
firstActual = OrderedSPILoader.getServices(OrderedSPINonSingletonFixture.class,
Collections.singleton(key));
+ Map<OrderedInterfaceFixtureImpl, OrderedSPINonSingletonFixture>
secondActual =
OrderedSPILoader.getServices(OrderedSPINonSingletonFixture.class,
Collections.singleton(key));
+ assertThat(firstActual.get(key),
is(not(sameInstance(secondActual.get(key)))));
}
}
diff --git
a/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ChildOrderedInterfaceFixtureImpl.java
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ChildOrderedInterfaceFixtureImpl.java
new file mode 100644
index 00000000000..fd80190a293
--- /dev/null
+++
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ChildOrderedInterfaceFixtureImpl.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.apache.shardingsphere.infra.spi.type.ordered.fixture.impl;
+
+public final class ChildOrderedInterfaceFixtureImpl extends
ParentOrderedInterfaceFixtureImpl {
+}
diff --git
a/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ComparableOrderedInterfaceFixtureImpl.java
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ComparableOrderedInterfaceFixtureImpl.java
new file mode 100644
index 00000000000..6703e8dea50
--- /dev/null
+++
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ComparableOrderedInterfaceFixtureImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.apache.shardingsphere.infra.spi.type.ordered.fixture.impl;
+
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedInterfaceFixture;
+
+import java.util.Objects;
+
+public final class ComparableOrderedInterfaceFixtureImpl implements
OrderedInterfaceFixture {
+
+ private final String value;
+
+ public ComparableOrderedInterfaceFixtureImpl(final String value) {
+ this.value = value;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (null == obj || getClass() != obj.getClass()) {
+ return false;
+ }
+ ComparableOrderedInterfaceFixtureImpl that =
(ComparableOrderedInterfaceFixtureImpl) obj;
+ return Objects.equals(value, that.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(value);
+ }
+}
diff --git
a/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ComparableOrderedSPIFixtureImpl.java
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ComparableOrderedSPIFixtureImpl.java
new file mode 100644
index 00000000000..6aea2c3813e
--- /dev/null
+++
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ComparableOrderedSPIFixtureImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.apache.shardingsphere.infra.spi.type.ordered.fixture.impl;
+
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPIFixture;
+
+public final class ComparableOrderedSPIFixtureImpl implements
OrderedSPIFixture<ComparableOrderedInterfaceFixtureImpl> {
+
+ @Override
+ public int getOrder() {
+ return 5;
+ }
+
+ @Override
+ public Class<ComparableOrderedInterfaceFixtureImpl> getTypeClass() {
+ return ComparableOrderedInterfaceFixtureImpl.class;
+ }
+}
diff --git
a/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ComparableOrderedSPINonSingletonFixtureImpl.java
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ComparableOrderedSPINonSingletonFixtureImpl.java
new file mode 100644
index 00000000000..61904bfb300
--- /dev/null
+++
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ComparableOrderedSPINonSingletonFixtureImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.apache.shardingsphere.infra.spi.type.ordered.fixture.impl;
+
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPINonSingletonFixture;
+
+public final class ComparableOrderedSPINonSingletonFixtureImpl implements
OrderedSPINonSingletonFixture<ComparableOrderedInterfaceFixtureImpl> {
+
+ @Override
+ public int getOrder() {
+ return 3;
+ }
+
+ @Override
+ public Class<ComparableOrderedInterfaceFixtureImpl> getTypeClass() {
+ return ComparableOrderedInterfaceFixtureImpl.class;
+ }
+}
diff --git
a/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ParentOrderedInterfaceFixtureImpl.java
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ParentOrderedInterfaceFixtureImpl.java
new file mode 100644
index 00000000000..bf8de81d4e9
--- /dev/null
+++
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ParentOrderedInterfaceFixtureImpl.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.apache.shardingsphere.infra.spi.type.ordered.fixture.impl;
+
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedInterfaceFixture;
+
+public class ParentOrderedInterfaceFixtureImpl implements
OrderedInterfaceFixture {
+}
diff --git
a/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ParentOrderedSPIFixtureImpl.java
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ParentOrderedSPIFixtureImpl.java
new file mode 100644
index 00000000000..dbcf58f3c1f
--- /dev/null
+++
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ParentOrderedSPIFixtureImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.apache.shardingsphere.infra.spi.type.ordered.fixture.impl;
+
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPIFixture;
+
+public final class ParentOrderedSPIFixtureImpl implements
OrderedSPIFixture<ParentOrderedInterfaceFixtureImpl> {
+
+ @Override
+ public int getOrder() {
+ return 1;
+ }
+
+ @Override
+ public Class<ParentOrderedInterfaceFixtureImpl> getTypeClass() {
+ return ParentOrderedInterfaceFixtureImpl.class;
+ }
+}
diff --git
a/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ParentOrderedSPINonSingletonFixtureImpl.java
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ParentOrderedSPINonSingletonFixtureImpl.java
new file mode 100644
index 00000000000..a7102e36752
--- /dev/null
+++
b/infra/spi/src/test/java/org/apache/shardingsphere/infra/spi/type/ordered/fixture/impl/ParentOrderedSPINonSingletonFixtureImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.apache.shardingsphere.infra.spi.type.ordered.fixture.impl;
+
+import
org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPINonSingletonFixture;
+
+public final class ParentOrderedSPINonSingletonFixtureImpl implements
OrderedSPINonSingletonFixture<ParentOrderedInterfaceFixtureImpl> {
+
+ @Override
+ public int getOrder() {
+ return 2;
+ }
+
+ @Override
+ public Class<ParentOrderedInterfaceFixtureImpl> getTypeClass() {
+ return ParentOrderedInterfaceFixtureImpl.class;
+ }
+}
diff --git
a/infra/spi/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPIFixture
b/infra/spi/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPIFixture
index ae4f00c062c..11cf5fc7770 100644
---
a/infra/spi/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPIFixture
+++
b/infra/spi/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPIFixture
@@ -15,4 +15,6 @@
# limitations under the License.
#
+org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.ParentOrderedSPIFixtureImpl
org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.OrderedSPIFixtureImpl
+org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.ComparableOrderedSPIFixtureImpl
diff --git
a/infra/spi/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPINonSingletonFixture
b/infra/spi/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPINonSingletonFixture
index d396cdccd4c..51976ffaa21 100644
---
a/infra/spi/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPINonSingletonFixture
+++
b/infra/spi/src/test/resources/META-INF/services/org.apache.shardingsphere.infra.spi.type.ordered.fixture.OrderedSPINonSingletonFixture
@@ -16,3 +16,5 @@
#
org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.OrderedSPINonSingletonFixtureImpl
+org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.ParentOrderedSPINonSingletonFixtureImpl
+org.apache.shardingsphere.infra.spi.type.ordered.fixture.impl.ComparableOrderedSPINonSingletonFixtureImpl