From d9d56d0574f4ff6e21851f6d0819334f72f9ee71 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E5=89=91=E9=91=AB?= <1064730540@qq.com>
Date: Sun, 5 Mar 2023 22:02:03 +0800
Subject: [PATCH 01/10] feat: kafka support #229 #231 #269
---
hippo4j-adapter/hippo4j-adapter-kafka/pom.xml | 24 ++
.../adapter/kafka/KafkaThreadPoolAdapter.java | 208 ++++++++++++++++++
hippo4j-adapter/pom.xml | 1 +
.../hippo4j/common/toolkit/ReflectUtil.java | 38 ++++
.../common/spi/MyArrayBlockingQueue.java | 17 ++
.../pom.xml | 49 +++++
.../adapter/kafka/example/MessageConsume.java | 35 +++
.../adapter/kafka/example/MessageProduce.java | 65 ++++++
.../ServerAdapterKafkaExampleApplication.java | 31 +++
.../src/main/resources/application.properties | 13 ++
hippo4j-example/pom.xml | 1 +
.../pom.xml | 24 ++
.../kafka/KafkaAdapterAutoConfiguration.java | 49 +++++
.../main/resources/META-INF/spring.factories | 1 +
.../pom.xml | 1 +
15 files changed, 557 insertions(+)
create mode 100644 hippo4j-adapter/hippo4j-adapter-kafka/pom.xml
create mode 100644 hippo4j-adapter/hippo4j-adapter-kafka/src/main/java/cn/hippo4j/adapter/kafka/KafkaThreadPoolAdapter.java
create mode 100644 hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/pom.xml
create mode 100644 hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/MessageConsume.java
create mode 100644 hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/MessageProduce.java
create mode 100644 hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/ServerAdapterKafkaExampleApplication.java
create mode 100644 hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/resources/application.properties
create mode 100644 hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/pom.xml
create mode 100644 hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/KafkaAdapterAutoConfiguration.java
create mode 100644 hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/src/main/resources/META-INF/spring.factories
diff --git a/hippo4j-adapter/hippo4j-adapter-kafka/pom.xml b/hippo4j-adapter/hippo4j-adapter-kafka/pom.xml
new file mode 100644
index 00000000..b963ef9f
--- /dev/null
+++ b/hippo4j-adapter/hippo4j-adapter-kafka/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ cn.hippo4j
+ hippo4j-adapter
+ ${revision}
+
+ hippo4j-adapter-kafka
+
+
+
+ cn.hippo4j
+ hippo4j-adapter-base
+ ${project.version}
+
+
+ org.springframework.kafka
+ spring-kafka
+ true
+
+
+
diff --git a/hippo4j-adapter/hippo4j-adapter-kafka/src/main/java/cn/hippo4j/adapter/kafka/KafkaThreadPoolAdapter.java b/hippo4j-adapter/hippo4j-adapter-kafka/src/main/java/cn/hippo4j/adapter/kafka/KafkaThreadPoolAdapter.java
new file mode 100644
index 00000000..21e417ac
--- /dev/null
+++ b/hippo4j-adapter/hippo4j-adapter-kafka/src/main/java/cn/hippo4j/adapter/kafka/KafkaThreadPoolAdapter.java
@@ -0,0 +1,208 @@
+/*
+ * 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 cn.hippo4j.adapter.kafka;
+
+import cn.hippo4j.adapter.base.ThreadPoolAdapter;
+import cn.hippo4j.adapter.base.ThreadPoolAdapterParameter;
+import cn.hippo4j.adapter.base.ThreadPoolAdapterState;
+import cn.hippo4j.common.config.ApplicationContextHolder;
+import cn.hippo4j.common.toolkit.ReflectUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.cglib.core.Constants;
+import org.springframework.context.ApplicationListener;
+import org.springframework.kafka.config.KafkaListenerEndpointRegistry;
+import org.springframework.kafka.listener.ConcurrentMessageListenerContainer;
+import org.springframework.kafka.listener.ContainerProperties;
+import org.springframework.kafka.listener.KafkaMessageListenerContainer;
+import org.springframework.kafka.listener.MessageListenerContainer;
+import org.springframework.kafka.support.TopicPartitionOffset;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import static cn.hippo4j.common.constant.ChangeThreadPoolConstants.CHANGE_DELIMITER;
+
+/**
+ * Kafka thread-pool adapter.
+ */
+@Slf4j
+public class KafkaThreadPoolAdapter implements ThreadPoolAdapter, ApplicationListener {
+
+ private KafkaListenerEndpointRegistry kafkaListenerEndpointRegistry;
+
+ @Override
+ public String mark() {
+ return "Kafka";
+ }
+
+ @Override
+ public ThreadPoolAdapterState getThreadPoolState(String identify) {
+ ThreadPoolAdapterState result = new ThreadPoolAdapterState();
+ MessageListenerContainer listenerContainer = kafkaListenerEndpointRegistry.getListenerContainer(identify);
+
+ if (listenerContainer == null) {
+ log.warn("[{}] Kafka consuming thread pool not found.", identify);
+ return result;
+ }
+
+ result.setThreadPoolKey(identify);
+ if (listenerContainer instanceof ConcurrentMessageListenerContainer) {
+ result.setCoreSize(((ConcurrentMessageListenerContainer, ?>) listenerContainer).getConcurrency());
+ result.setMaximumSize(result.getCoreSize());
+ } else {
+ result.setCoreSize(1);
+ result.setMaximumSize(1);
+ }
+ return result;
+ }
+
+ @Override
+ public List getThreadPoolStates() {
+ List adapterStateList = new ArrayList<>();
+ kafkaListenerEndpointRegistry.getListenerContainerIds().forEach(id -> adapterStateList.add(getThreadPoolState(id)));
+ return adapterStateList;
+ }
+
+ @Override
+ public boolean updateThreadPool(ThreadPoolAdapterParameter threadPoolAdapterParameter) {
+ String threadPoolKey = threadPoolAdapterParameter.getThreadPoolKey();
+ MessageListenerContainer listenerContainer = kafkaListenerEndpointRegistry.getListenerContainer(threadPoolKey);
+
+ if (listenerContainer == null) {
+ log.warn("[{}] Kafka consuming thread pool not found.", threadPoolKey);
+ return false;
+ }
+ if (!(listenerContainer instanceof ConcurrentMessageListenerContainer)) {
+ log.warn("[{}] Kafka consuming thread pool not support modify.", threadPoolKey);
+ return false;
+ }
+ ConcurrentMessageListenerContainer concurrentContainer = (ConcurrentMessageListenerContainer) listenerContainer;
+ int originalCoreSize = concurrentContainer.getConcurrency();
+ int originalMaximumPoolSize = originalCoreSize;
+ Integer concurrency = threadPoolAdapterParameter.getCorePoolSize();
+ if (originalCoreSize < concurrency) {
+ // add consumer
+ if (!addConsumer(threadPoolKey, concurrentContainer, originalCoreSize, concurrency)) {
+ return false;
+ }
+ } else {
+ // stop consumer
+ decreaseConsumer(threadPoolKey, concurrentContainer, originalCoreSize, concurrency);
+ }
+ concurrentContainer.setConcurrency(concurrency);
+ log.info("[{}] Kafka consumption thread pool parameter change. coreSize: {}, maximumSize: {}",
+ threadPoolKey,
+ String.format(CHANGE_DELIMITER, originalCoreSize, concurrency),
+ String.format(CHANGE_DELIMITER, originalMaximumPoolSize, concurrency));
+ return true;
+
+ }
+
+ /**
+ * @param threadPoolKey
+ * @param concurrentContainer
+ * @param originalCoreSize
+ * @param concurrency
+ * @since org.springframework.kafka.listener.ConcurrentMessageListenerContainer.doStop
+ */
+ private static void decreaseConsumer(String threadPoolKey, ConcurrentMessageListenerContainer concurrentContainer, int originalCoreSize, Integer concurrency) {
+ int targetDecrease = originalCoreSize - concurrency;
+ List containers = (List) ReflectUtil.getFieldValue(concurrentContainer, "containers");
+ Iterator iterator = containers.iterator();
+ int count = 0;
+ while (iterator.hasNext() && count < targetDecrease) {
+ KafkaMessageListenerContainer container = iterator.next();
+ if (container.isRunning()) {
+ container.stop(() -> {
+ });
+ count++;
+ }
+ }
+ log.info("[{}] Kafka consumption change. target decrease {} ,real decrease {}", threadPoolKey, targetDecrease, count);
+ }
+
+ /**
+ * @param threadPoolKey
+ * @param concurrentContainer
+ * @param originalCoreSize
+ * @param concurrency
+ * @return true success
+ * @since org.springframework.kafka.listener.ConcurrentMessageListenerContainer#doStart()
+ */
+ private static boolean addConsumer(String threadPoolKey, ConcurrentMessageListenerContainer concurrentContainer, int originalCoreSize, Integer concurrency) {
+ ContainerProperties containerProperties = concurrentContainer.getContainerProperties();
+ TopicPartitionOffset[] topicPartitions = containerProperties.getTopicPartitions();
+ if (topicPartitions != null && concurrency > topicPartitions.length) {
+ log.warn("[{}] Kafka consuming thread pool not support modify. " +
+ "When specific partitions are provided, the concurrency must be less than or "
+ + "equal to the number of partitions;", threadPoolKey);
+ return false;
+ }
+ List containers = (List) ReflectUtil.getFieldValue(concurrentContainer, "containers");
+ boolean alwaysClientIdSuffix = (Boolean) ReflectUtil.getFieldValue(concurrentContainer, "alwaysClientIdSuffix");
+ int size = containers.size();
+ for (int i = size; i < concurrency - originalCoreSize + size; i++) {
+ KafkaMessageListenerContainer container = ReflectUtil.invoke(concurrentContainer, "constructContainer", containerProperties, topicPartitions, i);
+ String beanName = concurrentContainer.getBeanName();
+ container.setBeanName((beanName != null ? beanName : "consumer") + "-" + i);
+ container.setApplicationContext(ApplicationContextHolder.getInstance());
+ if (concurrentContainer.getApplicationEventPublisher() != null) {
+ container.setApplicationEventPublisher(concurrentContainer.getApplicationEventPublisher());
+ }
+ container.setClientIdSuffix(concurrency > 1 || alwaysClientIdSuffix ? "-" + i : "");
+ container.setGenericErrorHandler(ReflectUtil.invoke(concurrentContainer, "getGenericErrorHandler"));
+ container.setAfterRollbackProcessor(ReflectUtil.invoke(concurrentContainer, "getAfterRollbackProcessor"));
+
+ Method getRecordInterceptor = ReflectUtil.findDeclaredMethod(concurrentContainer.getClass(), "getRecordInterceptor", Constants.EMPTY_CLASS_ARRAY);
+ ReflectUtil.setAccessible(getRecordInterceptor);
+ container.setRecordInterceptor(ReflectUtil.invoke(concurrentContainer, getRecordInterceptor));
+
+ Method isInterceptBeforeTx = ReflectUtil.findDeclaredMethod(concurrentContainer.getClass(), "isInterceptBeforeTx", Constants.EMPTY_CLASS_ARRAY);
+ ReflectUtil.setAccessible(isInterceptBeforeTx);
+ container.setInterceptBeforeTx(ReflectUtil.invoke(concurrentContainer, isInterceptBeforeTx));
+
+ container.setEmergencyStop(() -> {
+ concurrentContainer.stop(() -> {
+ });
+ ReflectUtil.invoke(concurrentContainer, "publishContainerStoppedEvent");
+ });
+ Method isPaused = ReflectUtil.findDeclaredMethod(concurrentContainer.getClass(), "isPaused", Constants.EMPTY_CLASS_ARRAY);
+ ReflectUtil.setAccessible(isPaused);
+
+ if (ReflectUtil.invoke(concurrentContainer, isPaused)) {
+ container.pause();
+ }
+ container.start();
+ containers.add(container);
+ }
+ return true;
+ }
+
+ @Override
+ public void onApplicationEvent(ApplicationStartedEvent event) {
+ try {
+ KafkaListenerEndpointRegistry kafkaListenerEndpointRegistry = ApplicationContextHolder.getBean(KafkaListenerEndpointRegistry.class);
+ this.kafkaListenerEndpointRegistry = kafkaListenerEndpointRegistry;
+ } catch (Exception ex) {
+ log.error("Failed to get Kafka thread pool.", ex);
+ }
+ }
+}
diff --git a/hippo4j-adapter/pom.xml b/hippo4j-adapter/pom.xml
index e65296d8..263f7ccd 100644
--- a/hippo4j-adapter/pom.xml
+++ b/hippo4j-adapter/pom.xml
@@ -17,6 +17,7 @@
hippo4j-adapter-alibaba-dubbo
hippo4j-adapter-rabbitmq
hippo4j-adapter-rocketmq
+ hippo4j-adapter-kafka
hippo4j-adapter-hystrix
hippo4j-adapter-spring-cloud-stream-rocketmq
hippo4j-adapter-spring-cloud-stream-rabbitmq
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/ReflectUtil.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/ReflectUtil.java
index 8f4fc5b4..317740ba 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/ReflectUtil.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/ReflectUtil.java
@@ -20,6 +20,7 @@ package cn.hippo4j.common.toolkit;
import cn.hippo4j.common.web.exception.IllegalException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.springframework.cglib.core.ReflectUtils;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
@@ -234,6 +235,28 @@ public class ReflectUtil {
return null;
}
+ /**
+ * Invoke.
+ *
+ * @param obj the obj
+ * @param methodName the method Name
+ * @param arguments parameters
+ * @return result for zhe method
+ */
+ @SuppressWarnings("unchecked")
+ public static T invoke(Object obj, String methodName, Object... arguments) {
+ try {
+ Method method = ReflectUtil.getMethodByName(obj.getClass(), methodName);
+ if (method == null) {
+ throw new IllegalException(methodName + "method not exists");
+ }
+ ReflectUtil.setAccessible(method);
+ return (T) method.invoke(obj, arguments);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new IllegalException(e);
+ }
+ }
+
/**
* Invoke.
*
@@ -283,4 +306,19 @@ public class ReflectUtil {
}
return null;
}
+
+ /**
+ *
+ * @param clazz
+ * @param methodName
+ * @param parameterTypes
+ * @return
+ */
+ public static Method findDeclaredMethod(Class clazz, String methodName, Class[] parameterTypes) {
+ try {
+ return ReflectUtils.findDeclaredMethod(clazz, methodName, parameterTypes);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/MyArrayBlockingQueue.java b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/MyArrayBlockingQueue.java
index 16b86e2e..47408032 100644
--- a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/MyArrayBlockingQueue.java
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/MyArrayBlockingQueue.java
@@ -1,3 +1,20 @@
+/*
+ * 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 cn.hippo4j.common.spi;
import cn.hippo4j.common.executor.support.CustomBlockingQueue;
diff --git a/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/pom.xml b/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/pom.xml
new file mode 100644
index 00000000..70e5d3a4
--- /dev/null
+++ b/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+ cn.hippo4j
+ hippo4j-example
+ ${revision}
+
+ hippo4j-spring-boot-starter-adapter-kafka-example
+
+
+ true
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.projectlombok
+ lombok
+
+
+ cn.hippo4j
+ hippo4j-spring-boot-starter-adapter-kafka
+ ${project.version}
+
+
+ cn.hippo4j
+ hippo4j-spring-boot-starter
+ ${project.version}
+
+
+ cn.hippo4j
+ hippo4j-example-core
+ ${revision}
+
+
+ org.springframework.kafka
+ spring-kafka
+
+
+
diff --git a/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/MessageConsume.java b/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/MessageConsume.java
new file mode 100644
index 00000000..c146b598
--- /dev/null
+++ b/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/MessageConsume.java
@@ -0,0 +1,35 @@
+/*
+ * 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 cn.hippo4j.springboot.starter.adapter.kafka.example;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.stereotype.Service;
+
+/**
+ * Message consume.
+ */
+@Slf4j
+@Service
+public class MessageConsume {
+
+ @KafkaListener(id = "testId1", topics = MessageProduce.TOPIC, groupId = "testGroup")
+ public void onMessage(String message) {
+ log.info("Message: {}", message);
+ }
+}
diff --git a/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/MessageProduce.java b/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/MessageProduce.java
new file mode 100644
index 00000000..d910d9e1
--- /dev/null
+++ b/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/MessageProduce.java
@@ -0,0 +1,65 @@
+/*
+ * 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 cn.hippo4j.springboot.starter.adapter.kafka.example;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.PostConstruct;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Message produce.
+ */
+@Slf4j
+@Component
+@RestController
+@AllArgsConstructor
+public class MessageProduce {
+
+ public static final String TOPIC = "test";
+
+ private final KafkaTemplate template;
+
+ @GetMapping("/message/send")
+ public String sendMessage() {
+ template.send(TOPIC, "testMessage");
+ return "success";
+ }
+
+ @PostConstruct
+ public void init() {
+ Thread t = new Thread(() -> {
+ while (true) {
+ String message = UUID.randomUUID().toString();
+ template.send(TOPIC, "autoTestMessage " + message);
+ try {
+ TimeUnit.SECONDS.sleep(3);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ t.start();
+ }
+}
diff --git a/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/ServerAdapterKafkaExampleApplication.java b/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/ServerAdapterKafkaExampleApplication.java
new file mode 100644
index 00000000..08e6f069
--- /dev/null
+++ b/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/example/ServerAdapterKafkaExampleApplication.java
@@ -0,0 +1,31 @@
+/*
+ * 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 cn.hippo4j.springboot.starter.adapter.kafka.example;
+
+import cn.hippo4j.core.enable.EnableDynamicThreadPool;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@EnableDynamicThreadPool
+@SpringBootApplication(scanBasePackages = {"cn.hippo4j.example.core", "cn.hippo4j.springboot.starter.adapter.kafka.example"})
+public class ServerAdapterKafkaExampleApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ServerAdapterKafkaExampleApplication.class, args);
+ }
+}
diff --git a/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/resources/application.properties b/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/resources/application.properties
new file mode 100644
index 00000000..ed0c980e
--- /dev/null
+++ b/hippo4j-example/hippo4j-spring-boot-starter-adapter-kafka-example/src/main/resources/application.properties
@@ -0,0 +1,13 @@
+server.port=8011
+
+debug=true
+
+spring.application.name=hippo4j-spring-boot-starter-adapter-kafka-example
+spring.dynamic.thread-pool.server-addr=http://localhost:6691
+spring.dynamic.thread-pool.namespace=prescription
+spring.dynamic.thread-pool.item-id=dynamic-threadpool-example
+spring.dynamic.thread-pool.username=admin
+spring.dynamic.thread-pool.password=123456
+
+
+spring.kafka.bootstrap-servers=localhost:9093,localhost:9094,localhost:9095
\ No newline at end of file
diff --git a/hippo4j-example/pom.xml b/hippo4j-example/pom.xml
index 0a3a623e..04daf166 100644
--- a/hippo4j-example/pom.xml
+++ b/hippo4j-example/pom.xml
@@ -26,6 +26,7 @@
hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rabbitmq-example
hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rocketmq-example
hippo4j-spring-boot-starter-adapter-rocketmq-example
+ hippo4j-spring-boot-starter-adapter-kafka-example
hippo4j-config-etcd-spring-boot-starter-example
hippo4j-config-nacos-spring-boot-1x-starter-example
hippo4j-config-apollo-spring-boot-1x-starter-example
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/pom.xml b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/pom.xml
new file mode 100644
index 00000000..1de46008
--- /dev/null
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ cn.hippo4j
+ hippo4j-spring-boot-starter-adapter
+ ${revision}
+
+ hippo4j-spring-boot-starter-adapter-kafka
+
+
+
+ cn.hippo4j
+ hippo4j-adapter-kafka
+ ${project.version}
+
+
+ org.springframework.kafka
+ spring-kafka
+ true
+
+
+
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/KafkaAdapterAutoConfiguration.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/KafkaAdapterAutoConfiguration.java
new file mode 100644
index 00000000..24107d28
--- /dev/null
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/src/main/java/cn/hippo4j/springboot/starter/adapter/kafka/KafkaAdapterAutoConfiguration.java
@@ -0,0 +1,49 @@
+/*
+ * 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 cn.hippo4j.springboot.starter.adapter.kafka;
+
+import cn.hippo4j.adapter.kafka.KafkaThreadPoolAdapter;
+import cn.hippo4j.common.config.ApplicationContextHolder;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.core.KafkaTemplate;
+
+/**
+ * Kafka adapter auto configuration.
+ */
+@Configuration
+@AutoConfigureAfter(KafkaAutoConfiguration.class)
+public class KafkaAdapterAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ApplicationContextHolder simpleApplicationContextHolder() {
+ return new ApplicationContextHolder();
+ }
+
+ @Bean
+ @SuppressWarnings("all")
+ @ConditionalOnBean(KafkaTemplate.class)
+ public KafkaThreadPoolAdapter kafkaThreadPoolAdapter(ApplicationContextHolder applicationContextHolder) {
+ return new KafkaThreadPoolAdapter();
+ }
+}
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/src/main/resources/META-INF/spring.factories b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..592fba93
--- /dev/null
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/hippo4j-spring-boot-starter-adapter-kafka/src/main/resources/META-INF/spring.factories
@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.hippo4j.springboot.starter.adapter.kafka.KafkaAdapterAutoConfiguration
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/pom.xml b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/pom.xml
index f2c5b783..1781a251 100644
--- a/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/pom.xml
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter-adapter/pom.xml
@@ -17,6 +17,7 @@
hippo4j-spring-boot-starter-adapter-alibaba-dubbo
hippo4j-spring-boot-starter-adapter-rabbitmq
hippo4j-spring-boot-starter-adapter-rocketmq
+ hippo4j-spring-boot-starter-adapter-kafka
hippo4j-spring-boot-starter-adapter-hystrix
hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rocketmq
hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rabbitmq
From d369391acadf9668e3914f2924625499e0b5449f Mon Sep 17 00:00:00 2001
From: machen
Date: Mon, 13 Mar 2023 21:15:48 +0800
Subject: [PATCH 02/10] Refactor blocking queue enum
---
.../support/BlockingQueueTypeEnum.java | 80 +++++++++++++------
1 file changed, 55 insertions(+), 25 deletions(-)
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
index 31ab11da..6d4d2d26 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
@@ -47,6 +47,11 @@ public enum BlockingQueueTypeEnum {
BlockingQueue of(Integer capacity) {
return new ArrayBlockingQueue<>(capacity);
}
+
+ @Override
+ BlockingQueue of() {
+ return new ArrayBlockingQueue<>(DEFAULT_CAPACITY);
+ }
},
/**
@@ -57,12 +62,22 @@ public enum BlockingQueueTypeEnum {
BlockingQueue of(Integer capacity) {
return new LinkedBlockingQueue<>(capacity);
}
+
+ @Override
+ BlockingQueue of() {
+ return new LinkedBlockingQueue<>();
+ }
},
/**
* {@link java.util.concurrent.LinkedBlockingDeque}
*/
LINKED_BLOCKING_DEQUE(3, "LinkedBlockingDeque") {
+ @Override
+ BlockingQueue of(Integer capacity) {
+ return new LinkedBlockingDeque<>(capacity);
+ }
+
@Override
BlockingQueue of() {
return new LinkedBlockingDeque<>();
@@ -73,6 +88,11 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.SynchronousQueue}
*/
SYNCHRONOUS_QUEUE(4, "SynchronousQueue") {
+ @Override
+ BlockingQueue of(Integer capacity) {
+ return new SynchronousQueue<>();
+ }
+
@Override
BlockingQueue of() {
return new SynchronousQueue<>();
@@ -83,6 +103,11 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.LinkedTransferQueue}
*/
LINKED_TRANSFER_QUEUE(5, "LinkedTransferQueue") {
+ @Override
+ BlockingQueue of(Integer capacity) {
+ return new LinkedTransferQueue<>();
+ }
+
@Override
BlockingQueue of() {
return new LinkedTransferQueue<>();
@@ -97,6 +122,11 @@ public enum BlockingQueueTypeEnum {
BlockingQueue of(Integer capacity) {
return new PriorityBlockingQueue<>(capacity);
}
+
+ @Override
+ BlockingQueue of() {
+ return new PriorityBlockingQueue<>();
+ }
},
/**
@@ -107,6 +137,11 @@ public enum BlockingQueueTypeEnum {
BlockingQueue of(Integer capacity) {
return new ResizableCapacityLinkedBlockingQueue<>(capacity);
}
+
+ @Override
+ BlockingQueue of() {
+ return new ResizableCapacityLinkedBlockingQueue<>();
+ }
};
@Getter
@@ -115,24 +150,6 @@ public enum BlockingQueueTypeEnum {
@Getter
private String name;
- BlockingQueueTypeEnum(int type, String name) {
- this.type = type;
- this.name = name;
- }
-
- private static Map typeToEnumMap;
- private static Map nameToEnumMap;
-
- static {
- final BlockingQueueTypeEnum[] values = BlockingQueueTypeEnum.values();
- typeToEnumMap = new HashMap<>(values.length);
- nameToEnumMap = new HashMap<>(values.length);
- for (BlockingQueueTypeEnum value : values) {
- typeToEnumMap.put(value.type, value);
- nameToEnumMap.put(value.name, value);
- }
- }
-
/**
* Create the specified implement of BlockingQueue with init capacity.
* Abstract method, depends on sub override
@@ -141,9 +158,7 @@ public enum BlockingQueueTypeEnum {
* @param the class of the objects in the BlockingQueue
* @return a BlockingQueue view of the specified T
*/
- BlockingQueue of(Integer capacity) {
- throw new NotSupportedException("该队列必须有界");
- }
+ abstract BlockingQueue of(Integer capacity);
/**
* Create the specified implement of BlockingQueue,has no capacity limit.
@@ -153,8 +168,24 @@ public enum BlockingQueueTypeEnum {
* @return a BlockingQueue view of the specified T
* @throws NotSupportedException
*/
- BlockingQueue of() {
- throw new NotSupportedException("该队列不支持有界");
+ abstract BlockingQueue of();
+
+ BlockingQueueTypeEnum(int type, String name) {
+ this.type = type;
+ this.name = name;
+ }
+
+ private static Map typeToEnumMap;
+ private static Map nameToEnumMap;
+
+ static {
+ final BlockingQueueTypeEnum[] values = BlockingQueueTypeEnum.values();
+ typeToEnumMap = new HashMap<>(values.length);
+ nameToEnumMap = new HashMap<>(values.length);
+ for (BlockingQueueTypeEnum value : values) {
+ typeToEnumMap.put(value.type, value);
+ nameToEnumMap.put(value.name, value);
+ }
}
/**
@@ -188,7 +219,7 @@ public enum BlockingQueueTypeEnum {
if (typeEnum == null) {
return null;
}
- return Objects.isNull(capacity) ? typeEnum.of() : typeEnum.of(capacity);
+ return typeEnum.of();
}
private static final int DEFAULT_CAPACITY = 1024;
@@ -197,7 +228,6 @@ public enum BlockingQueueTypeEnum {
DynamicThreadPoolServiceLoader.register(CustomBlockingQueue.class);
}
-
private static BlockingQueue customOrDefaultQueue(Integer capacity, Predicate predicate) {
Collection customBlockingQueues = DynamicThreadPoolServiceLoader
.getSingletonServiceInstances(CustomBlockingQueue.class);
From fd6b4a3e348ccd9fa65f4cc22d001c8b91ebd10b Mon Sep 17 00:00:00 2001
From: machen
Date: Mon, 13 Mar 2023 21:21:26 +0800
Subject: [PATCH 03/10] Refactor blocking queue enum
---
.../hippo4j/common/executor/support/BlockingQueueTypeEnum.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
index 6d4d2d26..a2f2c0e1 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
@@ -219,7 +219,7 @@ public enum BlockingQueueTypeEnum {
if (typeEnum == null) {
return null;
}
- return typeEnum.of();
+ return Objects.isNull(capacity) ? typeEnum.of() : typeEnum.of(capacity);
}
private static final int DEFAULT_CAPACITY = 1024;
From 0e87fff31f1a1c9bb106330cf9b903c0c92d8c5c Mon Sep 17 00:00:00 2001
From: zjHe <34431616+zjHe@users.noreply.github.com>
Date: Tue, 14 Mar 2023 10:21:00 +0800
Subject: [PATCH 04/10] feature:close and shutdown (#1103)
---
.../cn/hippo4j/springboot/starter/core/DiscoveryClient.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/DiscoveryClient.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/DiscoveryClient.java
index 0bc94ea3..92cb52e3 100644
--- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/DiscoveryClient.java
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/core/DiscoveryClient.java
@@ -92,6 +92,8 @@ public class DiscoveryClient implements DisposableBean {
String clientCloseUrlPath = Constants.BASE_PATH + "/client/close";
Result clientCloseResult;
try {
+ // close scheduledExecutor
+ this.scheduler.shutdown();
String groupKeyIp = new StringBuilder()
.append(instanceInfo.getGroupKey())
.append(Constants.GROUP_KEY_DELIMITER)
@@ -126,6 +128,9 @@ public class DiscoveryClient implements DisposableBean {
private boolean renew() {
Result renewResult;
try {
+ if (this.scheduler.isShutdown()) {
+ return false;
+ }
InstanceInfo.InstanceRenew instanceRenew = new InstanceInfo.InstanceRenew()
.setAppName(instanceInfo.getAppName())
.setInstanceId(instanceInfo.getInstanceId())
From 5e524fab44362f956d455978a0014fe00428bc17 Mon Sep 17 00:00:00 2001
From: ShengTongSun <35056992+ShengTongSun@users.noreply.github.com>
Date: Tue, 14 Mar 2023 13:09:28 +0800
Subject: [PATCH 05/10] IdentifyUtil 77 lines of StringBuilder can use string +
instead to simplify the code #1093 (#1104)
---
.../java/cn/hippo4j/core/toolkit/IdentifyUtil.java | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/hippo4j-core/src/main/java/cn/hippo4j/core/toolkit/IdentifyUtil.java b/hippo4j-core/src/main/java/cn/hippo4j/core/toolkit/IdentifyUtil.java
index 106d5c92..2d883772 100644
--- a/hippo4j-core/src/main/java/cn/hippo4j/core/toolkit/IdentifyUtil.java
+++ b/hippo4j-core/src/main/java/cn/hippo4j/core/toolkit/IdentifyUtil.java
@@ -74,13 +74,11 @@ public class IdentifyUtil {
ip = inetUtil.findFirstNonLoopBackHostInfo().getIpAddress();
port = environment.getProperty("server.port", "8080");
}
- String identify = new StringBuilder()
- .append(ip)
- .append(":")
- .append(port)
- .append(IDENTIFY_SLICER_SYMBOL)
- .append(CLIENT_IDENTIFICATION_VALUE)
- .toString();
+ String identify = ip
+ + ":"
+ + port
+ + IDENTIFY_SLICER_SYMBOL
+ + CLIENT_IDENTIFICATION_VALUE;
IDENTIFY = identify;
return identify;
}
From 0aa2c22bed165fdbdca907671970093b019121f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=82=93=E8=81=94=E9=BE=99?=
<53131003+2595001965@users.noreply.github.com>
Date: Tue, 14 Mar 2023 15:39:28 +0800
Subject: [PATCH 06/10] use lambda to simplify the code (#1105)
---
.../support/adpter/DynamicThreadPoolAdapterChoose.java | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/hippo4j-core/src/main/java/cn/hippo4j/core/executor/support/adpter/DynamicThreadPoolAdapterChoose.java b/hippo4j-core/src/main/java/cn/hippo4j/core/executor/support/adpter/DynamicThreadPoolAdapterChoose.java
index 39a4ba73..c3169502 100644
--- a/hippo4j-core/src/main/java/cn/hippo4j/core/executor/support/adpter/DynamicThreadPoolAdapterChoose.java
+++ b/hippo4j-core/src/main/java/cn/hippo4j/core/executor/support/adpter/DynamicThreadPoolAdapterChoose.java
@@ -76,9 +76,7 @@ public class DynamicThreadPoolAdapterChoose {
*/
public static void replace(Object executor, Executor dynamicThreadPoolExecutor) {
Optional dynamicThreadPoolAdapterOptional = DYNAMIC_THREAD_POOL_ADAPTERS.stream().filter(each -> each.match(executor)).findFirst();
- if (dynamicThreadPoolAdapterOptional.isPresent()) {
- dynamicThreadPoolAdapterOptional.get().replace(executor, dynamicThreadPoolExecutor);
- }
+ dynamicThreadPoolAdapterOptional.ifPresent(dynamicThreadPoolAdapter -> dynamicThreadPoolAdapter.replace(executor, dynamicThreadPoolExecutor));
}
/**
From 1f20678cb038bb50f0249c9044d93ac5d581d251 Mon Sep 17 00:00:00 2001
From: SquirrelChen <13654811+GM-Studio@users.noreply.github.com>
Date: Wed, 15 Mar 2023 11:29:07 +0800
Subject: [PATCH 07/10] feat(ThreadPoolMonitor) (#1108)
1. the ThreadPoolMonitor use the new api instead of the deprecated api
---
.../springboot/starter/monitor/ThreadPoolMonitorExecutor.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/monitor/ThreadPoolMonitorExecutor.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/monitor/ThreadPoolMonitorExecutor.java
index 04f2d938..7818fe42 100644
--- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/monitor/ThreadPoolMonitorExecutor.java
+++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/monitor/ThreadPoolMonitorExecutor.java
@@ -79,8 +79,8 @@ public class ThreadPoolMonitorExecutor implements ApplicationRunner, DisposableB
// Execute dynamic thread pool monitoring component.
collectScheduledExecutor.scheduleWithFixedDelay(
this::scheduleRunnable,
- properties.getInitialDelay(),
- properties.getCollectInterval(),
+ monitor.getInitialDelay(),
+ monitor.getCollectInterval(),
TimeUnit.MILLISECONDS);
if (GlobalThreadPoolManage.getThreadPoolNum() > 0) {
log.info("Dynamic thread pool: [{}]. The dynamic thread pool starts data collection and reporting.", getThreadPoolNum());
From f65dbb552101528ee5df3ae88fb14cfef824a67a Mon Sep 17 00:00:00 2001
From: zongyuanGitHub <187233878@qq.com>
Date: Wed, 15 Mar 2023 11:29:15 +0800
Subject: [PATCH 08/10] delete obsolete field (#1107)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: 启元
---
.../config/BootstrapConfigProperties.java | 24 -------------------
1 file changed, 24 deletions(-)
diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/BootstrapConfigProperties.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/BootstrapConfigProperties.java
index 57654b06..a5a435d2 100644
--- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/BootstrapConfigProperties.java
+++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/config/BootstrapConfigProperties.java
@@ -51,30 +51,6 @@ public class BootstrapConfigProperties implements BootstrapPropertiesInterface {
*/
private MonitorProperties monitor = new MonitorProperties();
- /***
- * Latest use {@link MonitorProperties#getEnable()}
- */
- @Deprecated
- private Boolean collect = Boolean.TRUE;
-
- /**
- * Latest use {@link MonitorProperties#getCollectTypes()}
- */
- @Deprecated
- private String collectType;
-
- /**
- * Latest use {@link MonitorProperties#getInitialDelay()}
- */
- @Deprecated
- private Long initialDelay = 10000L;
-
- /**
- * Latest use {@link MonitorProperties#getCollectInterval()}
- */
- @Deprecated
- private Long collectInterval = 5000L;
-
/**
* Config file type.
*/
From 72aa732688b5c4ed0d40afdb1605b2c304456582 Mon Sep 17 00:00:00 2001
From: Kevin
Date: Wed, 15 Mar 2023 12:20:37 +0800
Subject: [PATCH 09/10] refactor BlockingQueueTypeEnum (#1109)
---
.../support/BlockingQueueTypeEnum.java | 40 +++++++------------
1 file changed, 15 insertions(+), 25 deletions(-)
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
index a2f2c0e1..be4b603d 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
@@ -20,18 +20,8 @@ package cn.hippo4j.common.executor.support;
import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
import lombok.Getter;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.LinkedTransferQueue;
-import java.util.concurrent.PriorityBlockingQueue;
-import java.util.concurrent.SynchronousQueue;
+import java.util.*;
+import java.util.concurrent.*;
import java.util.function.Predicate;
/**
@@ -145,10 +135,10 @@ public enum BlockingQueueTypeEnum {
};
@Getter
- private Integer type;
+ private final Integer type;
@Getter
- private String name;
+ private final String name;
/**
* Create the specified implement of BlockingQueue with init capacity.
@@ -175,16 +165,16 @@ public enum BlockingQueueTypeEnum {
this.name = name;
}
- private static Map typeToEnumMap;
- private static Map nameToEnumMap;
+ private static final Map TYPE_TO_ENUM_MAP;
+ private static final Map NAME_TO_ENUM_MAP;
static {
final BlockingQueueTypeEnum[] values = BlockingQueueTypeEnum.values();
- typeToEnumMap = new HashMap<>(values.length);
- nameToEnumMap = new HashMap<>(values.length);
+ TYPE_TO_ENUM_MAP = new HashMap<>(values.length);
+ NAME_TO_ENUM_MAP = new HashMap<>(values.length);
for (BlockingQueueTypeEnum value : values) {
- typeToEnumMap.put(value.type, value);
- nameToEnumMap.put(value.name, value);
+ TYPE_TO_ENUM_MAP.put(value.type, value);
+ NAME_TO_ENUM_MAP.put(value.name, value);
}
}
@@ -198,7 +188,7 @@ public enum BlockingQueueTypeEnum {
* @return a BlockingQueue view of the specified T
*/
private static BlockingQueue of(String blockingQueueName, Integer capacity) {
- final BlockingQueueTypeEnum typeEnum = nameToEnumMap.get(blockingQueueName);
+ final BlockingQueueTypeEnum typeEnum = NAME_TO_ENUM_MAP.get(blockingQueueName);
if (typeEnum == null) {
return null;
}
@@ -215,7 +205,7 @@ public enum BlockingQueueTypeEnum {
* @return a BlockingQueue view of the specified T
*/
private static BlockingQueue of(int type, Integer capacity) {
- final BlockingQueueTypeEnum typeEnum = typeToEnumMap.get(type);
+ final BlockingQueueTypeEnum typeEnum = TYPE_TO_ENUM_MAP.get(type);
if (typeEnum == null) {
return null;
}
@@ -262,7 +252,7 @@ public enum BlockingQueueTypeEnum {
}
return customOrDefaultQueue(capacity,
- (customeQueue) -> Objects.equals(customeQueue.getName(), blockingQueueName));
+ (customerQueue) -> Objects.equals(customerQueue.getName(), blockingQueueName));
}
/**
@@ -293,7 +283,7 @@ public enum BlockingQueueTypeEnum {
* @return {@link BlockingQueueTypeEnum#name BlockingQueueTypeEnum.name } or "".
*/
public static String getBlockingQueueNameByType(int type) {
- return Optional.ofNullable(typeToEnumMap.get(type))
+ return Optional.ofNullable(TYPE_TO_ENUM_MAP.get(type))
.map(value -> value.getName())
.orElse("");
}
@@ -306,7 +296,7 @@ public enum BlockingQueueTypeEnum {
* @return enum {@link BlockingQueueTypeEnum}
*/
public static BlockingQueueTypeEnum getBlockingQueueTypeEnumByName(String name) {
- return Optional.ofNullable(nameToEnumMap.get(name))
+ return Optional.ofNullable(NAME_TO_ENUM_MAP.get(name))
.orElse(LINKED_BLOCKING_QUEUE);
}
}
From 275a8bfb928dd07ea482b9df393ff81212aca4b0 Mon Sep 17 00:00:00 2001
From: yanrongzhen
Date: Wed, 15 Mar 2023 13:27:22 +0800
Subject: [PATCH 10/10] Bruceyan/issue#1092 (#1102)
* refactor: Extension module
* refactor: Update packageNames and classNames, mark ServiceLoader deprecated.
* fix: remove some unused fields.
* method does not override or implement a method from a supertype
* fix: Modify some field names, add scoped target object filtering.
---
.../common/constant/HttpMediaType.java | 2 -
.../hippo4j/common/constant/HttpMethod.java | 2 -
.../common/constant/HttpResponseCode.java | 2 -
.../support/BlockingQueueTypeEnum.java | 13 ++-
.../support/NotSupportedException.java | 17 ++++
.../support/RejectedPolicyTypeEnum.java | 8 +-
.../hippo4j/common/extension/IExtension.java | 24 +++++
.../common/extension/IExtensionRequest.java | 24 +++++
.../extension/annotation/Realization.java | 35 +++++++
.../annotation/SingletonSPI.java | 3 +-
.../config/ExtensionRegisterBootstrap.java | 61 ++++++++++++
.../common/extension/reducer/AllMatch.java | 61 ++++++++++++
.../common/extension/reducer/AnyMatch.java | 60 ++++++++++++
.../common/extension/reducer/FirstOf.java | 54 +++++++++++
.../common/extension/reducer/None.java | 36 +++++++
.../common/extension/reducer/Reducer.java | 53 ++++++++++
.../common/extension/reducer/Reducers.java | 77 +++++++++++++++
.../support/ExtensionAutoConfiguration.java | 31 ++++++
.../extension/support/ExtensionCallback.java | 31 ++++++
.../extension/support/ExtensionInvoker.java | 60 ++++++++++++
.../extension/support/ExtensionRegistry.java | 97 +++++++++++++++++++
.../extension/support/IExtensionRegistry.java | 29 ++++++
.../common/extension/support/ReduceType.java | 26 +++++
.../ServiceLoaderInstantiationException.java | 2 +-
.../support/ServiceLoaderRegistry.java} | 12 ++-
.../cn/hippo4j/common/toolkit/Assert.java | 6 ++
.../cn/hippo4j/common/toolkit/ClassUtil.java | 53 ++++++++++
.../hippo4j/common/toolkit/http/HttpUtil.java | 2 -
.../toolkit/http/JdkHttpClientResponse.java | 2 -
.../common/toolkit/logtracing/LogMessage.java | 2 -
.../main/resources/META-INF/spring.factories | 1 +
.../extension/ExtensionInvokerTest.java | 81 ++++++++++++++++
.../extension/anymatch/AnyMatchExtImplA.java | 29 ++++++
.../extension/anymatch/AnyMatchExtImplB.java | 29 ++++++
.../anymatch/IAnyMatchExtension.java | 25 +++++
.../extension/firstof/FirstOfExtImplA.java | 29 ++++++
.../extension/firstof/FirstOfExtImplB.java | 29 ++++++
.../extension/firstof/IFirstOfExtension.java | 25 +++++
.../hippo4j/common/extension/spi/IOldSpi.java | 25 +++++
.../common/extension/spi/IOldSpiImplA.java | 27 ++++++
.../DynamicThreadPoolServiceLoaderTest.java | 31 +++---
.../hippo4j/common/spi/TestInterfaceSPI.java | 4 +-
.../common/spi/TestInterfaceSPIImpl.java | 4 +-
.../common/spi/TestSingletonInterfaceSPI.java | 5 +-
.../spi/TestSingletonInterfaceSPIImpl.java | 4 +-
.../cn.hippo4j.common.extension.spi.IOldSpi | 1 +
.../DynamicThreadPoolAdapterChoose.java | 6 +-
.../cn/hippo4j/core/toolkit/IdentifyUtil.java | 6 +-
.../monitor/ThreadPoolMonitorExecutor.java | 4 +-
.../ThreadPoolAdapterController.java | 4 +-
.../monitor/ReportingEventExecutor.java | 4 +-
.../provider/InstanceInfoProviderFactory.java | 6 +-
52 files changed, 1203 insertions(+), 61 deletions(-)
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/IExtension.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/IExtensionRequest.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/annotation/Realization.java
rename hippo4j-common/src/main/java/cn/hippo4j/common/{spi => extension}/annotation/SingletonSPI.java (94%)
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/config/ExtensionRegisterBootstrap.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/AllMatch.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/AnyMatch.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/FirstOf.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/None.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/Reducer.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/Reducers.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionAutoConfiguration.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionCallback.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionInvoker.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionRegistry.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/IExtensionRegistry.java
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ReduceType.java
rename hippo4j-common/src/main/java/cn/hippo4j/common/{spi => extension/support}/ServiceLoaderInstantiationException.java (96%)
rename hippo4j-common/src/main/java/cn/hippo4j/common/{spi/DynamicThreadPoolServiceLoader.java => extension/support/ServiceLoaderRegistry.java} (91%)
create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/ClassUtil.java
create mode 100644 hippo4j-common/src/main/resources/META-INF/spring.factories
create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/extension/ExtensionInvokerTest.java
create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/AnyMatchExtImplA.java
create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/AnyMatchExtImplB.java
create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/IAnyMatchExtension.java
create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/FirstOfExtImplA.java
create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/FirstOfExtImplB.java
create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/IFirstOfExtension.java
create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/extension/spi/IOldSpi.java
create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/extension/spi/IOldSpiImplA.java
create mode 100644 hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.extension.spi.IOldSpi
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMediaType.java b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMediaType.java
index 58caa1d8..fe45a4be 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMediaType.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMediaType.java
@@ -21,8 +21,6 @@ import cn.hippo4j.common.toolkit.StringUtil;
/**
* Http media type.
- *
- * @author Rongzhen Yan
*/
public final class HttpMediaType {
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMethod.java b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMethod.java
index fde14dfe..01bc3734 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMethod.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpMethod.java
@@ -19,8 +19,6 @@ package cn.hippo4j.common.constant;
/**
* Http method constants.
- *
- * @author Rongzhen Yan
*/
public class HttpMethod {
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpResponseCode.java b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpResponseCode.java
index 72e9df94..e5117937 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpResponseCode.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/constant/HttpResponseCode.java
@@ -19,8 +19,6 @@ package cn.hippo4j.common.constant;
/**
* Http response code.
- *
- * @author Rongzhen Yan
*/
public class HttpResponseCode {
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
index be4b603d..a1a77720 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/BlockingQueueTypeEnum.java
@@ -17,7 +17,7 @@
package cn.hippo4j.common.executor.support;
-import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
import lombok.Getter;
import java.util.*;
@@ -33,6 +33,7 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.ArrayBlockingQueue}
*/
ARRAY_BLOCKING_QUEUE(1, "ArrayBlockingQueue") {
+
@Override
BlockingQueue of(Integer capacity) {
return new ArrayBlockingQueue<>(capacity);
@@ -48,6 +49,7 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.LinkedBlockingQueue}
*/
LINKED_BLOCKING_QUEUE(2, "LinkedBlockingQueue") {
+
@Override
BlockingQueue of(Integer capacity) {
return new LinkedBlockingQueue<>(capacity);
@@ -63,6 +65,7 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.LinkedBlockingDeque}
*/
LINKED_BLOCKING_DEQUE(3, "LinkedBlockingDeque") {
+
@Override
BlockingQueue of(Integer capacity) {
return new LinkedBlockingDeque<>(capacity);
@@ -78,6 +81,7 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.SynchronousQueue}
*/
SYNCHRONOUS_QUEUE(4, "SynchronousQueue") {
+
@Override
BlockingQueue of(Integer capacity) {
return new SynchronousQueue<>();
@@ -93,6 +97,7 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.LinkedTransferQueue}
*/
LINKED_TRANSFER_QUEUE(5, "LinkedTransferQueue") {
+
@Override
BlockingQueue of(Integer capacity) {
return new LinkedTransferQueue<>();
@@ -108,6 +113,7 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.PriorityBlockingQueue}
*/
PRIORITY_BLOCKING_QUEUE(6, "PriorityBlockingQueue") {
+
@Override
BlockingQueue of(Integer capacity) {
return new PriorityBlockingQueue<>(capacity);
@@ -123,6 +129,7 @@ public enum BlockingQueueTypeEnum {
* {@link ResizableCapacityLinkedBlockingQueue}
*/
RESIZABLE_LINKED_BLOCKING_QUEUE(9, "ResizableCapacityLinkedBlockingQueue") {
+
@Override
BlockingQueue of(Integer capacity) {
return new ResizableCapacityLinkedBlockingQueue<>(capacity);
@@ -215,11 +222,11 @@ public enum BlockingQueueTypeEnum {
private static final int DEFAULT_CAPACITY = 1024;
static {
- DynamicThreadPoolServiceLoader.register(CustomBlockingQueue.class);
+ ServiceLoaderRegistry.register(CustomBlockingQueue.class);
}
private static BlockingQueue customOrDefaultQueue(Integer capacity, Predicate predicate) {
- Collection customBlockingQueues = DynamicThreadPoolServiceLoader
+ Collection customBlockingQueues = ServiceLoaderRegistry
.getSingletonServiceInstances(CustomBlockingQueue.class);
return customBlockingQueues.stream()
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/NotSupportedException.java b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/NotSupportedException.java
index 9a9e8105..f3996a05 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/NotSupportedException.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/NotSupportedException.java
@@ -1,3 +1,20 @@
+/*
+ * 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 cn.hippo4j.common.executor.support;
import cn.hippo4j.common.web.exception.AbstractException;
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/RejectedPolicyTypeEnum.java b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/RejectedPolicyTypeEnum.java
index eed9b2ae..98272da1 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/RejectedPolicyTypeEnum.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/executor/support/RejectedPolicyTypeEnum.java
@@ -17,7 +17,7 @@
package cn.hippo4j.common.executor.support;
-import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
import lombok.Getter;
import java.util.Collection;
@@ -59,7 +59,7 @@ public enum RejectedPolicyTypeEnum {
}
static {
- DynamicThreadPoolServiceLoader.register(CustomRejectedExecutionHandler.class);
+ ServiceLoaderRegistry.register(CustomRejectedExecutionHandler.class);
}
public static RejectedExecutionHandler createPolicy(String name) {
@@ -70,7 +70,7 @@ public enum RejectedPolicyTypeEnum {
if (rejectedTypeEnum != null) {
return rejectedTypeEnum.rejectedHandler;
}
- Collection customRejectedExecutionHandlers = DynamicThreadPoolServiceLoader
+ Collection customRejectedExecutionHandlers = ServiceLoaderRegistry
.getSingletonServiceInstances(CustomRejectedExecutionHandler.class);
Optional customRejected = customRejectedExecutionHandlers.stream()
.filter(each -> Objects.equals(name, each.getName()))
@@ -85,7 +85,7 @@ public enum RejectedPolicyTypeEnum {
.map(each -> each.rejectedHandler)
.findFirst();
RejectedExecutionHandler resultRejected = rejectedTypeEnum.orElseGet(() -> {
- Collection customRejectedExecutionHandlers = DynamicThreadPoolServiceLoader
+ Collection customRejectedExecutionHandlers = ServiceLoaderRegistry
.getSingletonServiceInstances(CustomRejectedExecutionHandler.class);
Optional customRejected = customRejectedExecutionHandlers.stream()
.filter(each -> Objects.equals(type, each.getType()))
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/IExtension.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/IExtension.java
new file mode 100644
index 00000000..cae01c93
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/IExtension.java
@@ -0,0 +1,24 @@
+/*
+ * 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 cn.hippo4j.common.extension;
+
+/**
+ * Top level interface of extension-point.
+ */
+public interface IExtension {
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/IExtensionRequest.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/IExtensionRequest.java
new file mode 100644
index 00000000..1ad5e14e
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/IExtensionRequest.java
@@ -0,0 +1,24 @@
+/*
+ * 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 cn.hippo4j.common.extension;
+
+/**
+ * Top level interface of extension-point request obj.
+ */
+public interface IExtensionRequest {
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/annotation/Realization.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/annotation/Realization.java
new file mode 100644
index 00000000..d0981ac6
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/annotation/Realization.java
@@ -0,0 +1,35 @@
+/*
+ * 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 cn.hippo4j.common.extension.annotation;
+
+import org.springframework.stereotype.Component;
+
+import java.lang.annotation.*;
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@Component
+public @interface Realization {
+
+ String code() default "DEFAULT_CODE";
+
+ String name() default "DEFAULT_NAME";
+
+ int order() default 0;
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/spi/annotation/SingletonSPI.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/annotation/SingletonSPI.java
similarity index 94%
rename from hippo4j-common/src/main/java/cn/hippo4j/common/spi/annotation/SingletonSPI.java
rename to hippo4j-common/src/main/java/cn/hippo4j/common/extension/annotation/SingletonSPI.java
index 1b04524c..7f1620ba 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/spi/annotation/SingletonSPI.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/annotation/SingletonSPI.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package cn.hippo4j.common.spi.annotation;
+package cn.hippo4j.common.extension.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -27,5 +27,6 @@ import java.lang.annotation.Target;
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
+@Deprecated
public @interface SingletonSPI {
}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/config/ExtensionRegisterBootstrap.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/config/ExtensionRegisterBootstrap.java
new file mode 100644
index 00000000..0dbae207
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/config/ExtensionRegisterBootstrap.java
@@ -0,0 +1,61 @@
+/*
+ * 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 cn.hippo4j.common.extension.config;
+
+import cn.hippo4j.common.extension.IExtension;
+import cn.hippo4j.common.extension.annotation.Realization;
+import cn.hippo4j.common.extension.support.ExtensionRegistry;
+import cn.hippo4j.common.toolkit.ClassUtil;
+import org.springframework.aop.scope.ScopedProxyUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Extension register bootstrap
+ */
+public class ExtensionRegisterBootstrap implements ApplicationContextAware, ApplicationRunner {
+
+ private ExtensionRegistry registry = ExtensionRegistry.getInstance();
+
+ private ApplicationContext applicationContext;
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ @Override
+ public void run(ApplicationArguments args) throws Exception {
+ applicationContext.getBeansWithAnnotation(Realization.class)
+ .entrySet().stream()
+ .filter(entry -> !filterClass(entry.getKey(), entry.getValue()))
+ .forEach(entry -> registry.register((IExtension) entry.getValue()));
+ }
+
+ private boolean filterClass(String beanName, Object bean) {
+ return bean.getClass().isAssignableFrom(IExtension.class) ||
+ ScopedProxyUtils.isScopedTarget(beanName) ||
+ !(bean instanceof IExtension);
+ }
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/AllMatch.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/AllMatch.java
new file mode 100644
index 00000000..f1f37e7f
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/AllMatch.java
@@ -0,0 +1,61 @@
+/*
+ * 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 cn.hippo4j.common.extension.reducer;
+
+import cn.hippo4j.common.extension.IExtension;
+import cn.hippo4j.common.extension.support.ReduceType;
+import cn.hippo4j.common.toolkit.CollectionUtil;
+import lombok.Getter;
+import lombok.NonNull;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/**
+ * All-match extension reduce policy.
+ */
+public class AllMatch extends Reducer {
+
+ @Getter
+ private final Predicate predicate;
+
+ public AllMatch(@NonNull Predicate predicate) {
+ Objects.requireNonNull(predicate);
+ this.predicate = predicate;
+ }
+
+ @Override
+ public Boolean reduce() {
+ if (CollectionUtil.isEmpty(realizations)) {
+ return false;
+ } else {
+ for (IExtension realization : realizations) {
+ if (!predicate.test(getCallback().apply(realization))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public ReduceType reducerType() {
+ return ReduceType.ALL;
+ }
+
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/AnyMatch.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/AnyMatch.java
new file mode 100644
index 00000000..66305b00
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/AnyMatch.java
@@ -0,0 +1,60 @@
+/*
+ * 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 cn.hippo4j.common.extension.reducer;
+
+import cn.hippo4j.common.extension.IExtension;
+import cn.hippo4j.common.extension.support.ReduceType;
+import cn.hippo4j.common.toolkit.CollectionUtil;
+import lombok.Getter;
+import lombok.NonNull;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/**
+ * Any-match extension reduce policy.
+ */
+public class AnyMatch extends Reducer {
+
+ @Getter
+ private final Predicate predicate;
+
+ public AnyMatch(@NonNull Predicate predicate) {
+ Objects.requireNonNull(predicate);
+ this.predicate = predicate;
+ }
+
+ @Override
+ public Boolean reduce() {
+ if (CollectionUtil.isEmpty(realizations)) {
+ return false;
+ }
+ for (IExtension extension : realizations) {
+ if (predicate.test(getCallback().apply(extension))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public ReduceType reducerType() {
+ return ReduceType.FIRST;
+ }
+
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/FirstOf.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/FirstOf.java
new file mode 100644
index 00000000..c7aa6981
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/FirstOf.java
@@ -0,0 +1,54 @@
+/*
+ * 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 cn.hippo4j.common.extension.reducer;
+
+import cn.hippo4j.common.extension.IExtension;
+import cn.hippo4j.common.extension.support.ReduceType;
+import lombok.NonNull;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/**
+ * First-of extension reduce policy.
+ */
+public class FirstOf extends Reducer {
+
+ private Predicate predicate;
+
+ public FirstOf(@NonNull Predicate predicate) {
+ Objects.requireNonNull(predicate);
+ this.predicate = predicate;
+ }
+
+ @Override
+ public ReduceType reducerType() {
+ return ReduceType.FIRST;
+ }
+
+ @Override
+ public Element reduce() {
+ for (IExtension extension : realizations) {
+ Element element = getCallback().apply(extension);
+ if (null == predicate || predicate.test(element)) {
+ return element;
+ }
+ }
+ return null;
+ }
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/None.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/None.java
new file mode 100644
index 00000000..3280a832
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/None.java
@@ -0,0 +1,36 @@
+/*
+ * 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 cn.hippo4j.common.extension.reducer;
+
+import cn.hippo4j.common.extension.support.ReduceType;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class None extends Reducer> {
+
+ @Override
+ public ReduceType reducerType() {
+ return ReduceType.NONE;
+ }
+
+ @Override
+ public List reduce() {
+ return realizations.stream().map(getCallback()).collect(Collectors.toList());
+ }
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/Reducer.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/Reducer.java
new file mode 100644
index 00000000..079625d2
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/Reducer.java
@@ -0,0 +1,53 @@
+/*
+ * 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 cn.hippo4j.common.extension.reducer;
+
+import cn.hippo4j.common.extension.IExtension;
+import cn.hippo4j.common.extension.IExtensionRequest;
+import cn.hippo4j.common.extension.support.ExtensionCallback;
+import cn.hippo4j.common.extension.support.ReduceType;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class Reducer {
+
+ @Getter
+ private Result result;
+
+ @Setter
+ protected IExtensionRequest request;
+
+ @Setter
+ protected List realizations;
+
+ @Setter
+ @Getter
+ private ExtensionCallback callback;
+
+ public abstract Result reduce();
+
+ public abstract ReduceType reducerType();
+
+ public String reduceName() {
+ return this.getClass().getSimpleName();
+ }
+
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/Reducers.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/Reducers.java
new file mode 100644
index 00000000..b3ea7186
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/Reducers.java
@@ -0,0 +1,77 @@
+/*
+ * 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 cn.hippo4j.common.extension.reducer;
+
+import lombok.NonNull;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+
+@SuppressWarnings("all")
+public class Reducers {
+
+ /**
+ * No reduce policy needed.
+ *
+ * @return None type reducer
+ */
+ public static Reducer> none() {
+ return new None<>();
+ }
+
+ /**
+ * Build a FirstOf Reducer.
+ *
+ * @param predicate the condition predicate.
+ * @return FirstOf Policy Reducer.
+ */
+ public static Reducer firstOf(@NonNull Predicate predicate) {
+ return new FirstOf<>(predicate);
+ }
+
+ /**
+ * Build a FirstOf Not-null Reducer.
+ *
+ * @return FirstOf Not-null Policy Reducer.
+ */
+ public static Reducer firstOfNotNull() {
+ return new FirstOf<>(Objects::nonNull);
+ }
+
+ /**
+ * Build a AnyMatch Reducer.
+ *
+ * @param predicate the condition predicate.
+ * @return AnyMatch Policy Reducer.
+ */
+ public static Reducer anyMatch(Predicate predicate) {
+ return new AnyMatch<>(predicate);
+ }
+
+ /**
+ * Build a AllMatch Reducer
+ *
+ * @param predicate the condition predicate.
+ * @return AllMatch Policy Reducer.
+ */
+ public static Reducer allMatch(@NonNull Predicate predicate) {
+ return new AllMatch<>(predicate);
+ }
+
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionAutoConfiguration.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionAutoConfiguration.java
new file mode 100644
index 00000000..78736976
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionAutoConfiguration.java
@@ -0,0 +1,31 @@
+/*
+ * 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 cn.hippo4j.common.extension.support;
+
+import cn.hippo4j.common.extension.config.ExtensionRegisterBootstrap;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ExtensionAutoConfiguration {
+
+ @Bean
+ public ExtensionRegisterBootstrap bootstrap() {
+ return new ExtensionRegisterBootstrap();
+ }
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionCallback.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionCallback.java
new file mode 100644
index 00000000..5c71fcb5
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionCallback.java
@@ -0,0 +1,31 @@
+/*
+ * 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 cn.hippo4j.common.extension.support;
+
+import java.util.function.Function;
+
+/**
+ * Callback function of extension invocation.
+ * @param
+ * @param
+ */
+@FunctionalInterface
+public interface ExtensionCallback extends Function {
+
+ R apply(T extension);
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionInvoker.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionInvoker.java
new file mode 100644
index 00000000..0c748680
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionInvoker.java
@@ -0,0 +1,60 @@
+/*
+ * 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 cn.hippo4j.common.extension.support;
+
+import cn.hippo4j.common.extension.IExtension;
+import cn.hippo4j.common.extension.reducer.Reducer;
+import cn.hippo4j.common.extension.reducer.Reducers;
+import cn.hippo4j.common.toolkit.Assert;
+import cn.hippo4j.common.toolkit.CollectionUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Extension point invoker.
+ *
+ * Providing extension-point invocation ability that supports the use of reducing policy.
+ */
+public class ExtensionInvoker {
+
+ private static final ExtensionRegistry registry = ExtensionRegistry.getInstance();
+
+ public static List reduceExecute(Class targetClz,
+ ExtensionCallback callback) {
+ return reduceExecute(targetClz, callback, Reducers.none());
+ }
+
+ @SuppressWarnings("unchecked")
+ public static R reduceExecute(Class targetClz,
+ ExtensionCallback callback,
+ Reducer reducer) {
+ Assert.isTrue(IExtension.class.isAssignableFrom(targetClz),
+ "can not execute extension point. please implement base extension interface(" + IExtension.class.getName() + ") first.");
+
+ List realizations = registry.find(targetClz);
+ if (CollectionUtil.isEmpty(realizations)) {
+ realizations = new ArrayList<>(ServiceLoaderRegistry.getSingletonServiceInstances(targetClz));
+ }
+ Assert.notEmpty(realizations, "can not find any extension realizations with interface: " + targetClz.getName());
+
+ reducer.setRealizations(realizations);
+ reducer.setCallback((ExtensionCallback) callback);
+ return reducer.reduce();
+ }
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionRegistry.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionRegistry.java
new file mode 100644
index 00000000..b835446c
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionRegistry.java
@@ -0,0 +1,97 @@
+/*
+ * 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 cn.hippo4j.common.extension.support;
+
+import cn.hippo4j.common.extension.IExtension;
+import cn.hippo4j.common.extension.annotation.Realization;
+import cn.hippo4j.common.toolkit.CollectionUtil;
+import cn.hippo4j.common.toolkit.logtracing.LogMessage;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.util.ClassUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Extension registry
+ */
+@Slf4j
+public class ExtensionRegistry implements IExtensionRegistry {
+
+ private final Map, List> registry = new ConcurrentHashMap<>();
+
+ private static ExtensionRegistry INSTANCE;
+
+ private ExtensionRegistry() {
+ }
+
+ public static ExtensionRegistry getInstance() {
+ if (null == INSTANCE) {
+ synchronized (ExtensionRegistry.class) {
+ if (null == INSTANCE) {
+ INSTANCE = new ExtensionRegistry();
+ }
+ }
+ }
+ return INSTANCE;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void register(IExtension realization) {
+
+ Class> implClass = realization.getClass();
+ if (AopUtils.isAopProxy(implClass)) {
+ implClass = ClassUtils.getUserClass(implClass);
+ }
+ Realization annotation = implClass.getAnnotation(Realization.class);
+
+ Class>[] interfaces = implClass.getInterfaces();
+
+ for (Class> intf : interfaces) {
+ if (IExtension.class.isAssignableFrom(intf)) {
+ this.register((Class) intf, realization);
+ }
+ }
+ }
+
+ private void register(Class extends IExtension> extension, IExtension realization) {
+ if (!registry.containsKey(extension) || CollectionUtil.isEmpty(registry.get(extension))) {
+ List realizations = new ArrayList<>();
+ realizations.add(realization);
+ registry.put(extension, realizations);
+ } else {
+ if (registry.get(extension).contains(realization)) {
+ log.warn(LogMessage.getInstance()
+ .kv("realizationClassName", realization.getClass().getName())
+ .msg("Extension realization already registered, skip."));
+ }
+ List realizations = registry.get(extension);
+ realizations.add(realization);
+ registry.put(extension, realizations);
+ }
+ }
+
+ @Override
+ public List find(Class extends IExtension> extension) {
+ return registry.get(extension);
+ }
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/IExtensionRegistry.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/IExtensionRegistry.java
new file mode 100644
index 00000000..d1ffa3e2
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/IExtensionRegistry.java
@@ -0,0 +1,29 @@
+/*
+ * 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 cn.hippo4j.common.extension.support;
+
+import cn.hippo4j.common.extension.IExtension;
+
+import java.util.List;
+
+public interface IExtensionRegistry {
+
+ void register(IExtension realization);
+
+ List find(Class extends IExtension> extension);
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ReduceType.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ReduceType.java
new file mode 100644
index 00000000..7a4fe9e4
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ReduceType.java
@@ -0,0 +1,26 @@
+/*
+ * 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 cn.hippo4j.common.extension.support;
+
+public enum ReduceType {
+
+ NONE,
+ ALL,
+ FIRST,
+ UNKNOWN
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/spi/ServiceLoaderInstantiationException.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ServiceLoaderInstantiationException.java
similarity index 96%
rename from hippo4j-common/src/main/java/cn/hippo4j/common/spi/ServiceLoaderInstantiationException.java
rename to hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ServiceLoaderInstantiationException.java
index 496d44dd..239817d1 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/spi/ServiceLoaderInstantiationException.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ServiceLoaderInstantiationException.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package cn.hippo4j.common.spi;
+package cn.hippo4j.common.extension.support;
/**
* Service loader instantiation exception.
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoader.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ServiceLoaderRegistry.java
similarity index 91%
rename from hippo4j-common/src/main/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoader.java
rename to hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ServiceLoaderRegistry.java
index cd96e4a8..493dd489 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoader.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ServiceLoaderRegistry.java
@@ -15,9 +15,10 @@
* limitations under the License.
*/
-package cn.hippo4j.common.spi;
+package cn.hippo4j.common.extension.support;
-import cn.hippo4j.common.spi.annotation.SingletonSPI;
+import cn.hippo4j.common.extension.annotation.SingletonSPI;
+import cn.hippo4j.common.extension.support.ServiceLoaderInstantiationException;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
@@ -29,9 +30,10 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
- * Dynamic thread-pool service loader.
+ * Dynamic thread-pool SPI service loader.
*/
-public class DynamicThreadPoolServiceLoader {
+@Deprecated
+public class ServiceLoaderRegistry {
/**
* safe container。
@@ -40,7 +42,7 @@ public class DynamicThreadPoolServiceLoader {
*/
private static final Map, Collection>> SERVICES = new ConcurrentHashMap<>();
- private DynamicThreadPoolServiceLoader() {
+ private ServiceLoaderRegistry() {
}
/**
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/Assert.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/Assert.java
index 327152a0..3dee268f 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/Assert.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/Assert.java
@@ -38,6 +38,12 @@ public class Assert {
isTrue(expression, "[Assertion failed] - this expression must be true");
}
+ public static void isEmpty(Collection> collection, String message) {
+ if (!CollectionUtil.isEmpty(collection)) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
public static void isNull(Object object, String message) {
if (object != null) {
throw new IllegalArgumentException(message);
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/ClassUtil.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/ClassUtil.java
new file mode 100644
index 00000000..94950732
--- /dev/null
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/ClassUtil.java
@@ -0,0 +1,53 @@
+/*
+ * 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 cn.hippo4j.common.toolkit;
+
+/**
+ * Class Util.
+ */
+public class ClassUtil {
+
+ /**
+ * get class loader
+ *
+ * @param clazz
+ * @return class loader
+ */
+ public static ClassLoader getClassLoader(Class> clazz) {
+ ClassLoader cl = null;
+ try {
+ cl = Thread.currentThread().getContextClassLoader();
+ } catch (Throwable ex) {
+ // Cannot access thread context ClassLoader - falling back to system class loader...
+ }
+ if (cl == null) {
+ // No thread context class loader -> use class loader of this class.
+ cl = clazz.getClassLoader();
+ if (cl == null) {
+ // getClassLoader() returning null indicates the bootstrap ClassLoader
+ try {
+ cl = ClassLoader.getSystemClassLoader();
+ } catch (Throwable ex) {
+ // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
+ }
+ }
+ }
+
+ return cl;
+ }
+}
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/HttpUtil.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/HttpUtil.java
index 1aaae2b9..138b6076 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/HttpUtil.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/HttpUtil.java
@@ -43,8 +43,6 @@ import static cn.hippo4j.common.constant.HttpHeaderConstants.CONTENT_LENGTH;
/**
* Http request utilities.
- *
- * @author Rongzhen Yan
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/JdkHttpClientResponse.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/JdkHttpClientResponse.java
index 683b6191..c6671aaa 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/JdkHttpClientResponse.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/http/JdkHttpClientResponse.java
@@ -30,8 +30,6 @@ import java.util.Map;
/**
* Represents a client-side HTTP response with JDK implementation
- *
- * @author Rongzhen Yan
*/
public class JdkHttpClientResponse implements HttpClientResponse {
diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/logtracing/LogMessage.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/logtracing/LogMessage.java
index 47ef1090..b961a4b2 100644
--- a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/logtracing/LogMessage.java
+++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/logtracing/LogMessage.java
@@ -28,8 +28,6 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* Log message.
- *
- * @author Rongzhen Yan
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LogMessage {
diff --git a/hippo4j-common/src/main/resources/META-INF/spring.factories b/hippo4j-common/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..520aa9cd
--- /dev/null
+++ b/hippo4j-common/src/main/resources/META-INF/spring.factories
@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.hippo4j.common.extension.support.ExtensionAutoConfiguration
\ No newline at end of file
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/extension/ExtensionInvokerTest.java b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/ExtensionInvokerTest.java
new file mode 100644
index 00000000..343bb745
--- /dev/null
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/ExtensionInvokerTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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 cn.hippo4j.common.extension;
+
+import cn.hippo4j.common.extension.anymatch.AnyMatchExtImplA;
+import cn.hippo4j.common.extension.anymatch.AnyMatchExtImplB;
+import cn.hippo4j.common.extension.anymatch.IAnyMatchExtension;
+import cn.hippo4j.common.extension.firstof.FirstOfExtImplA;
+import cn.hippo4j.common.extension.firstof.FirstOfExtImplB;
+import cn.hippo4j.common.extension.firstof.IFirstOfExtension;
+import cn.hippo4j.common.extension.reducer.Reducers;
+import cn.hippo4j.common.extension.spi.IOldSpi;
+import cn.hippo4j.common.extension.support.ExtensionInvoker;
+import cn.hippo4j.common.extension.support.ExtensionRegistry;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
+import org.assertj.core.util.Lists;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Objects;
+
+import static org.junit.Assert.*;
+
+public class ExtensionInvokerTest {
+
+ @Before
+ public void before() {
+ ExtensionRegistry.getInstance().register(new FirstOfExtImplA());
+ ExtensionRegistry.getInstance().register(new FirstOfExtImplB());
+ ExtensionRegistry.getInstance().register(new AnyMatchExtImplA());
+ ExtensionRegistry.getInstance().register(new AnyMatchExtImplB());
+
+ ServiceLoaderRegistry.register(IOldSpi.class);
+ }
+ @Test
+ public void test() {
+
+ Integer arg = 20;
+ // first-of
+ Integer res1 = ExtensionInvoker.reduceExecute(IFirstOfExtension.class, (ext) -> ext.foo(arg),
+ Reducers.firstOfNotNull());
+ assertEquals(arg, res1);
+
+ // any-match
+ Boolean res2 = ExtensionInvoker.reduceExecute(IAnyMatchExtension.class, (ext) -> ext.foo(arg),
+ Reducers.anyMatch(Objects::nonNull));
+ assertTrue(res2);
+
+ // none
+ List res3 = ExtensionInvoker.reduceExecute(IFirstOfExtension.class, (ext) -> ext.foo(arg));
+ assertArrayEquals(res3.toArray(new Integer[0]), Lists.newArrayList(null, arg).toArray());
+
+ // all-match
+ Boolean res4 = ExtensionInvoker.reduceExecute(IAnyMatchExtension.class, (ext) -> ext.foo(arg),
+ Reducers.allMatch(Objects::nonNull));
+ assertTrue(res4);
+
+ }
+
+ @Test
+ public void test_spi_old() {
+ Boolean res1 = ExtensionInvoker.reduceExecute(IOldSpi.class, IOldSpi::foo, Reducers.firstOfNotNull());
+ assertTrue(res1);
+ }
+}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/AnyMatchExtImplA.java b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/AnyMatchExtImplA.java
new file mode 100644
index 00000000..75829c75
--- /dev/null
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/AnyMatchExtImplA.java
@@ -0,0 +1,29 @@
+/*
+ * 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 cn.hippo4j.common.extension.anymatch;
+
+import cn.hippo4j.common.extension.annotation.Realization;
+
+@Realization
+public class AnyMatchExtImplA implements IAnyMatchExtension {
+
+ @Override
+ public Integer foo(Integer arg) {
+ return arg > 0 ? arg : null;
+ }
+}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/AnyMatchExtImplB.java b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/AnyMatchExtImplB.java
new file mode 100644
index 00000000..8aef4d5d
--- /dev/null
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/AnyMatchExtImplB.java
@@ -0,0 +1,29 @@
+/*
+ * 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 cn.hippo4j.common.extension.anymatch;
+
+import cn.hippo4j.common.extension.annotation.Realization;
+
+@Realization
+public class AnyMatchExtImplB implements IAnyMatchExtension {
+
+ @Override
+ public Integer foo(Integer arg) {
+ return arg > 0 ? arg : null;
+ }
+}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/IAnyMatchExtension.java b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/IAnyMatchExtension.java
new file mode 100644
index 00000000..94d9adec
--- /dev/null
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/anymatch/IAnyMatchExtension.java
@@ -0,0 +1,25 @@
+/*
+ * 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 cn.hippo4j.common.extension.anymatch;
+
+import cn.hippo4j.common.extension.IExtension;
+
+public interface IAnyMatchExtension extends IExtension {
+
+ Integer foo(Integer arg);
+}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/FirstOfExtImplA.java b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/FirstOfExtImplA.java
new file mode 100644
index 00000000..b5a17c87
--- /dev/null
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/FirstOfExtImplA.java
@@ -0,0 +1,29 @@
+/*
+ * 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 cn.hippo4j.common.extension.firstof;
+
+import cn.hippo4j.common.extension.annotation.Realization;
+
+@Realization
+public class FirstOfExtImplA implements IFirstOfExtension {
+
+ @Override
+ public Integer foo(Integer arg) {
+ return null;
+ }
+}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/FirstOfExtImplB.java b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/FirstOfExtImplB.java
new file mode 100644
index 00000000..7128541a
--- /dev/null
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/FirstOfExtImplB.java
@@ -0,0 +1,29 @@
+/*
+ * 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 cn.hippo4j.common.extension.firstof;
+
+import cn.hippo4j.common.extension.annotation.Realization;
+
+@Realization
+public class FirstOfExtImplB implements IFirstOfExtension {
+
+ @Override
+ public Integer foo(Integer arg) {
+ return arg;
+ }
+}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/IFirstOfExtension.java b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/IFirstOfExtension.java
new file mode 100644
index 00000000..f7c8c333
--- /dev/null
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/firstof/IFirstOfExtension.java
@@ -0,0 +1,25 @@
+/*
+ * 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 cn.hippo4j.common.extension.firstof;
+
+import cn.hippo4j.common.extension.IExtension;
+
+public interface IFirstOfExtension extends IExtension {
+
+ Integer foo(Integer arg);
+}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/extension/spi/IOldSpi.java b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/spi/IOldSpi.java
new file mode 100644
index 00000000..7391d6f1
--- /dev/null
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/spi/IOldSpi.java
@@ -0,0 +1,25 @@
+/*
+ * 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 cn.hippo4j.common.extension.spi;
+
+import cn.hippo4j.common.extension.IExtension;
+
+public interface IOldSpi extends IExtension {
+
+ Boolean foo();
+}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/extension/spi/IOldSpiImplA.java b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/spi/IOldSpiImplA.java
new file mode 100644
index 00000000..d161b024
--- /dev/null
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/spi/IOldSpiImplA.java
@@ -0,0 +1,27 @@
+/*
+ * 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 cn.hippo4j.common.extension.spi;
+
+public class IOldSpiImplA implements IOldSpi {
+
+ @Override
+ public Boolean foo() {
+ System.out.println(this.getClass().getName());
+ return true;
+ }
+}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoaderTest.java b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoaderTest.java
index 0e8e7fba..ddd3f317 100644
--- a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoaderTest.java
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoaderTest.java
@@ -19,6 +19,7 @@ package cn.hippo4j.common.spi;
import java.util.Collection;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -28,46 +29,46 @@ import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertTrue;
/**
- * test {@link DynamicThreadPoolServiceLoader}
+ * test {@link ServiceLoaderRegistry}
*/
public final class DynamicThreadPoolServiceLoaderTest {
@Test
public void assertRegister() {
- DynamicThreadPoolServiceLoader.register(Collection.class);
- Collection> collections = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(Collection.class);
+ ServiceLoaderRegistry.register(Collection.class);
+ Collection> collections = ServiceLoaderRegistry.getSingletonServiceInstances(Collection.class);
assertTrue(collections.isEmpty());
}
@Test
public void assertGetSingletonServiceInstances() {
- DynamicThreadPoolServiceLoader.register(TestSingletonInterfaceSPI.class);
- Collection instances = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class);
+ ServiceLoaderRegistry.register(TestSingletonInterfaceSPI.class);
+ Collection instances = ServiceLoaderRegistry.getSingletonServiceInstances(TestSingletonInterfaceSPI.class);
assertThat(instances.size(), equalTo(1));
- assertThat(instances.iterator().next(), is(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next()));
+ assertThat(instances.iterator().next(), is(ServiceLoaderRegistry.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next()));
}
@Test
public void assertNewServiceInstances() {
- DynamicThreadPoolServiceLoader.register(TestSingletonInterfaceSPI.class);
- Collection instances = DynamicThreadPoolServiceLoader.newServiceInstances(TestSingletonInterfaceSPI.class);
+ ServiceLoaderRegistry.register(TestSingletonInterfaceSPI.class);
+ Collection instances = ServiceLoaderRegistry.newServiceInstances(TestSingletonInterfaceSPI.class);
assertThat(instances.size(), equalTo(1));
- assertThat(instances.iterator().next(), not(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next()));
+ assertThat(instances.iterator().next(), not(ServiceLoaderRegistry.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next()));
}
@Test
public void assertGetServiceInstancesWhenIsSingleton() {
- DynamicThreadPoolServiceLoader.register(TestSingletonInterfaceSPI.class);
- Collection instances = DynamicThreadPoolServiceLoader.getServiceInstances(TestSingletonInterfaceSPI.class);
- assertThat(instances.iterator().next(), is(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next()));
+ ServiceLoaderRegistry.register(TestSingletonInterfaceSPI.class);
+ Collection instances = ServiceLoaderRegistry.getServiceInstances(TestSingletonInterfaceSPI.class);
+ assertThat(instances.iterator().next(), is(ServiceLoaderRegistry.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next()));
}
@Test
public void assertGetServiceInstancesWhenNotSingleton() {
- DynamicThreadPoolServiceLoader.register(TestInterfaceSPI.class);
- Collection instances = DynamicThreadPoolServiceLoader.getServiceInstances(TestInterfaceSPI.class);
- assertThat(instances.iterator().next(), not(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestInterfaceSPI.class).iterator().next()));
+ ServiceLoaderRegistry.register(TestInterfaceSPI.class);
+ Collection instances = ServiceLoaderRegistry.getServiceInstances(TestInterfaceSPI.class);
+ assertThat(instances.iterator().next(), not(ServiceLoaderRegistry.getSingletonServiceInstances(TestInterfaceSPI.class).iterator().next()));
}
}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPI.java b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPI.java
index 69baeb8a..2851f7e9 100644
--- a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPI.java
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPI.java
@@ -17,8 +17,10 @@
package cn.hippo4j.common.spi;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
+
/**
- * test {@link DynamicThreadPoolServiceLoader}
+ * test {@link ServiceLoaderRegistry}
*/
public interface TestInterfaceSPI {
}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPIImpl.java b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPIImpl.java
index 833a5919..fc8b2779 100644
--- a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPIImpl.java
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPIImpl.java
@@ -17,8 +17,10 @@
package cn.hippo4j.common.spi;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
+
/**
- * test {@link DynamicThreadPoolServiceLoader}
+ * test {@link ServiceLoaderRegistry}
*/
public class TestInterfaceSPIImpl implements TestInterfaceSPI {
}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPI.java b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPI.java
index 739e08d3..e530d6bb 100644
--- a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPI.java
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPI.java
@@ -17,10 +17,11 @@
package cn.hippo4j.common.spi;
-import cn.hippo4j.common.spi.annotation.SingletonSPI;
+import cn.hippo4j.common.extension.annotation.SingletonSPI;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
/**
- * test {@link DynamicThreadPoolServiceLoader}
+ * test {@link ServiceLoaderRegistry}
*/
@SingletonSPI
public interface TestSingletonInterfaceSPI {
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPIImpl.java b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPIImpl.java
index d5babd2a..6aeb275f 100644
--- a/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPIImpl.java
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPIImpl.java
@@ -17,8 +17,10 @@
package cn.hippo4j.common.spi;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
+
/**
- * test {@link DynamicThreadPoolServiceLoader}
+ * test {@link ServiceLoaderRegistry}
*/
public class TestSingletonInterfaceSPIImpl implements TestSingletonInterfaceSPI {
}
diff --git a/hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.extension.spi.IOldSpi b/hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.extension.spi.IOldSpi
new file mode 100644
index 00000000..29dcbcac
--- /dev/null
+++ b/hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.extension.spi.IOldSpi
@@ -0,0 +1 @@
+cn.hippo4j.common.extension.spi.IOldSpiImplA
\ No newline at end of file
diff --git a/hippo4j-core/src/main/java/cn/hippo4j/core/executor/support/adpter/DynamicThreadPoolAdapterChoose.java b/hippo4j-core/src/main/java/cn/hippo4j/core/executor/support/adpter/DynamicThreadPoolAdapterChoose.java
index c3169502..420fc353 100644
--- a/hippo4j-core/src/main/java/cn/hippo4j/core/executor/support/adpter/DynamicThreadPoolAdapterChoose.java
+++ b/hippo4j-core/src/main/java/cn/hippo4j/core/executor/support/adpter/DynamicThreadPoolAdapterChoose.java
@@ -17,7 +17,7 @@
package cn.hippo4j.core.executor.support.adpter;
-import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.core.executor.DynamicThreadPoolExecutor;
import cn.hippo4j.core.executor.support.spi.DynamicThreadPoolAdapterSPI;
@@ -83,8 +83,8 @@ public class DynamicThreadPoolAdapterChoose {
* Load SPI customer adapter.
*/
private static void loadCustomerAdapter() {
- DynamicThreadPoolServiceLoader.register(DynamicThreadPoolAdapterSPI.class);
- Collection instances = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(DynamicThreadPoolAdapterSPI.class);
+ ServiceLoaderRegistry.register(DynamicThreadPoolAdapterSPI.class);
+ Collection instances = ServiceLoaderRegistry.getSingletonServiceInstances(DynamicThreadPoolAdapterSPI.class);
if (CollectionUtil.isEmpty(instances)) {
return;
}
diff --git a/hippo4j-core/src/main/java/cn/hippo4j/core/toolkit/IdentifyUtil.java b/hippo4j-core/src/main/java/cn/hippo4j/core/toolkit/IdentifyUtil.java
index 2d883772..00a67f26 100644
--- a/hippo4j-core/src/main/java/cn/hippo4j/core/toolkit/IdentifyUtil.java
+++ b/hippo4j-core/src/main/java/cn/hippo4j/core/toolkit/IdentifyUtil.java
@@ -19,7 +19,7 @@ package cn.hippo4j.core.toolkit;
import cn.hippo4j.common.api.ClientNetworkService;
import cn.hippo4j.common.config.ApplicationContextHolder;
-import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.common.toolkit.IdUtil;
import cn.hippo4j.common.toolkit.Joiner;
@@ -39,7 +39,7 @@ import static cn.hippo4j.common.constant.Constants.IDENTIFY_SLICER_SYMBOL;
public class IdentifyUtil {
static {
- DynamicThreadPoolServiceLoader.register(ClientNetworkService.class);
+ ServiceLoaderRegistry.register(ClientNetworkService.class);
}
/**
@@ -63,7 +63,7 @@ public class IdentifyUtil {
if (StringUtil.isNotBlank(IDENTIFY)) {
return IDENTIFY;
}
- String[] customerNetwork = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(ClientNetworkService.class)
+ String[] customerNetwork = ServiceLoaderRegistry.getSingletonServiceInstances(ClientNetworkService.class)
.stream().findFirst().map(each -> each.getNetworkIpPort(environment)).orElse(null);
String ip;
String port;
diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/monitor/ThreadPoolMonitorExecutor.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/monitor/ThreadPoolMonitorExecutor.java
index 7818fe42..5b91d02d 100644
--- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/monitor/ThreadPoolMonitorExecutor.java
+++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/config/springboot/starter/monitor/ThreadPoolMonitorExecutor.java
@@ -27,7 +27,7 @@ import java.util.concurrent.TimeUnit;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.design.builder.ThreadFactoryBuilder;
-import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties;
import cn.hippo4j.config.springboot.starter.config.MonitorProperties;
@@ -74,7 +74,7 @@ public class ThreadPoolMonitorExecutor implements ApplicationRunner, DisposableB
List collectTypes = Arrays.asList(monitor.getCollectTypes().split(","));
ApplicationContextHolder.getBeansOfType(ThreadPoolMonitor.class).forEach((beanName, bean) -> threadPoolMonitors.add(bean));
Collection dynamicThreadPoolMonitors =
- DynamicThreadPoolServiceLoader.getSingletonServiceInstances(DynamicThreadPoolMonitor.class);
+ ServiceLoaderRegistry.getSingletonServiceInstances(DynamicThreadPoolMonitor.class);
dynamicThreadPoolMonitors.stream().filter(each -> collectTypes.contains(each.getType())).forEach(each -> threadPoolMonitors.add(each));
// Execute dynamic thread pool monitoring component.
collectScheduledExecutor.scheduleWithFixedDelay(
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/controller/ThreadPoolAdapterController.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/controller/ThreadPoolAdapterController.java
index 6bc1bad8..decbc0fc 100644
--- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/controller/ThreadPoolAdapterController.java
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/controller/ThreadPoolAdapterController.java
@@ -21,7 +21,7 @@ import cn.hippo4j.adapter.base.ThreadPoolAdapter;
import cn.hippo4j.adapter.base.ThreadPoolAdapterParameter;
import cn.hippo4j.adapter.base.ThreadPoolAdapterState;
import cn.hippo4j.common.api.ClientNetworkService;
-import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.common.web.base.Result;
import cn.hippo4j.common.web.base.Results;
@@ -59,7 +59,7 @@ public class ThreadPoolAdapterController {
ThreadPoolAdapterState threadPoolState = each.getThreadPoolState(requestParameter.getThreadPoolKey());
String active = environment.getProperty("spring.profiles.active", "UNKNOWN");
threadPoolState.setActive(active.toUpperCase());
- String[] customerNetwork = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(ClientNetworkService.class)
+ String[] customerNetwork = ServiceLoaderRegistry.getSingletonServiceInstances(ClientNetworkService.class)
.stream().findFirst().map(network -> network.getNetworkIpPort(environment)).orElse(null);
String clientAddress;
if (customerNetwork != null) {
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/monitor/ReportingEventExecutor.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/monitor/ReportingEventExecutor.java
index b4edecc0..b908c3e6 100644
--- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/monitor/ReportingEventExecutor.java
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/monitor/ReportingEventExecutor.java
@@ -20,7 +20,7 @@ package cn.hippo4j.springboot.starter.monitor;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.design.builder.ThreadFactoryBuilder;
import cn.hippo4j.common.monitor.Message;
-import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.common.toolkit.ThreadUtil;
@@ -119,7 +119,7 @@ public class ReportingEventExecutor implements Runnable, CommandLineRunner, Disp
new Integer(collectType.split(",").length),
ThreadFactoryBuilder.builder().daemon(true).prefix("client.scheduled.collect.data").build());
Collection dynamicThreadPoolMonitors =
- DynamicThreadPoolServiceLoader.getSingletonServiceInstances(ThreadPoolMonitor.class);
+ ServiceLoaderRegistry.getSingletonServiceInstances(ThreadPoolMonitor.class);
Map threadPoolMonitorMap = ApplicationContextHolder.getBeansOfType(ThreadPoolMonitor.class);
boolean customerDynamicThreadPoolMonitorFlag = CollectionUtil.isNotEmpty(dynamicThreadPoolMonitors) || CollectionUtil.isNotEmpty(threadPoolMonitorMap);
if (customerDynamicThreadPoolMonitorFlag) {
diff --git a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/provider/InstanceInfoProviderFactory.java b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/provider/InstanceInfoProviderFactory.java
index 41a20e9e..02b8f047 100644
--- a/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/provider/InstanceInfoProviderFactory.java
+++ b/hippo4j-spring-boot/hippo4j-spring-boot-starter/src/main/java/cn/hippo4j/springboot/starter/provider/InstanceInfoProviderFactory.java
@@ -19,7 +19,7 @@ package cn.hippo4j.springboot.starter.provider;
import cn.hippo4j.common.api.ClientNetworkService;
import cn.hippo4j.common.model.InstanceInfo;
-import cn.hippo4j.common.spi.DynamicThreadPoolServiceLoader;
+import cn.hippo4j.common.extension.support.ServiceLoaderRegistry;
import cn.hippo4j.common.toolkit.ContentUtil;
import cn.hippo4j.core.toolkit.IdentifyUtil;
import cn.hippo4j.core.toolkit.inet.InetUtils;
@@ -40,7 +40,7 @@ import static cn.hippo4j.core.toolkit.IdentifyUtil.CLIENT_IDENTIFICATION_VALUE;
public final class InstanceInfoProviderFactory {
static {
- DynamicThreadPoolServiceLoader.register(ClientNetworkService.class);
+ ServiceLoaderRegistry.register(ClientNetworkService.class);
}
/**
@@ -69,7 +69,7 @@ public final class InstanceInfoProviderFactory {
.setIpApplicationName(CloudCommonIdUtil.getIpApplicationName(environment, inetUtils))
.setHostName(InetAddress.getLocalHost().getHostAddress()).setAppName(applicationName)
.setPort(port).setClientBasePath(contextPath).setGroupKey(ContentUtil.getGroupKey(itemId, namespace));
- String[] customerNetwork = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(ClientNetworkService.class)
+ String[] customerNetwork = ServiceLoaderRegistry.getSingletonServiceInstances(ClientNetworkService.class)
.stream().findFirst().map(each -> each.getNetworkIpPort(environment)).orElse(null);
String callBackUrl = new StringBuilder().append(Optional.ofNullable(customerNetwork).map(each -> each[0]).orElse(instanceInfo.getHostName())).append(":")
.append(Optional.ofNullable(customerNetwork).map(each -> each[1]).orElse(port)).append(instanceInfo.getClientBasePath())