From 275a8bfb928dd07ea482b9df393ff81212aca4b0 Mon Sep 17 00:00:00 2001 From: yanrongzhen Date: Wed, 15 Mar 2023 13:27:22 +0800 Subject: [PATCH] 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 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 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 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())