From ed0847759d0777db799ffb79c62efcb8a9525960 Mon Sep 17 00:00:00 2001 From: weihubeats Date: Wed, 9 Nov 2022 09:48:44 +0800 Subject: [PATCH] add spi test (#957) * Simplified DynamicThreadPool usage * Simplified DynamicThreadPool usage * init * add test * format code * format code * update doc * Simplify the code --- .../spi/DynamicThreadPoolServiceLoader.java | 16 +++++- .../common/spi/annotation/SingletonSPI.java | 31 +++++++++++ .../DynamicThreadPoolServiceLoaderTest.java | 52 +++++++++++++++++++ .../hippo4j/common/spi/TestInterfaceSPI.java | 24 +++++++++ .../common/spi/TestInterfaceSPIImpl.java | 24 +++++++++ .../common/spi/TestSingletonInterfaceSPI.java | 27 ++++++++++ .../spi/TestSingletonInterfaceSPIImpl.java | 24 +++++++++ .../cn.hippo4j.common.spi.TestInterfaceSPI | 18 +++++++ ...ppo4j.common.spi.TestSingletonInterfaceSPI | 18 +++++++ ...ThreadPoolElasticSearchMonitorHandler.java | 1 + .../monitor/ThreadPoolMonitorExecutor.java | 25 ++++----- 11 files changed, 247 insertions(+), 13 deletions(-) create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/spi/annotation/SingletonSPI.java create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPI.java create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPIImpl.java create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPI.java create mode 100644 hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPIImpl.java create mode 100644 hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.spi.TestInterfaceSPI create mode 100644 hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.spi.TestSingletonInterfaceSPI diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoader.java b/hippo4j-common/src/main/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoader.java index ecfdbacd..da118e98 100644 --- a/hippo4j-common/src/main/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoader.java +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/spi/DynamicThreadPoolServiceLoader.java @@ -26,12 +26,14 @@ import java.util.ServiceLoader; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import cn.hippo4j.common.spi.annotation.SingletonSPI; + /** * Dynamic thread-pool service loader. */ public class DynamicThreadPoolServiceLoader { - private static final Map, Collection> SERVICES = new ConcurrentHashMap(); + private static final Map, Collection> SERVICES = new ConcurrentHashMap<>(); /** * Register. @@ -59,6 +61,17 @@ public class DynamicThreadPoolServiceLoader { return result; } + /** + * Get Service instances + * + * @param serviceClass serviceClass + * @param + * @return + */ + public static Collection getServiceInstances(final Class serviceClass) { + return null == serviceClass.getAnnotation(SingletonSPI.class) ? newServiceInstances(serviceClass) : getSingletonServiceInstances(serviceClass); + } + /** * Get singleton service instances. * @@ -66,6 +79,7 @@ public class DynamicThreadPoolServiceLoader { * @param * @return */ + @SuppressWarnings("unchecked") public static Collection getSingletonServiceInstances(final Class service) { return (Collection) SERVICES.getOrDefault(service, Collections.emptyList()); } diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/spi/annotation/SingletonSPI.java b/hippo4j-common/src/main/java/cn/hippo4j/common/spi/annotation/SingletonSPI.java new file mode 100644 index 00000000..1b04524c --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/spi/annotation/SingletonSPI.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.spi.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation of singleton SPI. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface SingletonSPI { +} 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 8387793c..0e8e7fba 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 @@ -17,5 +17,57 @@ package cn.hippo4j.common.spi; +import java.util.Collection; + +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertTrue; + +/** + * test {@link DynamicThreadPoolServiceLoader} + */ public final class DynamicThreadPoolServiceLoaderTest { + + @Test + public void assertRegister() { + DynamicThreadPoolServiceLoader.register(Collection.class); + Collection collections = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(Collection.class); + assertTrue(collections.isEmpty()); + } + + @Test + public void assertGetSingletonServiceInstances() { + DynamicThreadPoolServiceLoader.register(TestSingletonInterfaceSPI.class); + Collection instances = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class); + assertThat(instances.size(), equalTo(1)); + assertThat(instances.iterator().next(), is(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next())); + } + + @Test + public void assertNewServiceInstances() { + DynamicThreadPoolServiceLoader.register(TestSingletonInterfaceSPI.class); + Collection instances = DynamicThreadPoolServiceLoader.newServiceInstances(TestSingletonInterfaceSPI.class); + assertThat(instances.size(), equalTo(1)); + assertThat(instances.iterator().next(), not(DynamicThreadPoolServiceLoader.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())); + + } + + @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())); + + } } 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 new file mode 100644 index 00000000..69baeb8a --- /dev/null +++ b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPI.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.spi; + +/** + * test {@link DynamicThreadPoolServiceLoader} + */ +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 new file mode 100644 index 00000000..833a5919 --- /dev/null +++ b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestInterfaceSPIImpl.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.spi; + +/** + * test {@link DynamicThreadPoolServiceLoader} + */ +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 new file mode 100644 index 00000000..739e08d3 --- /dev/null +++ b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPI.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.spi; + +import cn.hippo4j.common.spi.annotation.SingletonSPI; + +/** + * test {@link DynamicThreadPoolServiceLoader} + */ +@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 new file mode 100644 index 00000000..d5babd2a --- /dev/null +++ b/hippo4j-common/src/test/java/cn/hippo4j/common/spi/TestSingletonInterfaceSPIImpl.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.spi; + +/** + * test {@link DynamicThreadPoolServiceLoader} + */ +public class TestSingletonInterfaceSPIImpl implements TestSingletonInterfaceSPI { +} diff --git a/hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.spi.TestInterfaceSPI b/hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.spi.TestInterfaceSPI new file mode 100644 index 00000000..66d393f8 --- /dev/null +++ b/hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.spi.TestInterfaceSPI @@ -0,0 +1,18 @@ +# +# 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. +# + +cn.hippo4j.common.spi.TestInterfaceSPIImpl \ No newline at end of file diff --git a/hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.spi.TestSingletonInterfaceSPI b/hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.spi.TestSingletonInterfaceSPI new file mode 100644 index 00000000..bcfaa43b --- /dev/null +++ b/hippo4j-common/src/test/resources/META-INF/services/cn.hippo4j.common.spi.TestSingletonInterfaceSPI @@ -0,0 +1,18 @@ +# +# 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. +# + +cn.hippo4j.common.spi.TestSingletonInterfaceSPIImpl \ No newline at end of file diff --git a/hippo4j-monitor/hippo4j-monitor-elasticsearch/src/main/java/cn/hippo4j/monitor/elasticsearch/DynamicThreadPoolElasticSearchMonitorHandler.java b/hippo4j-monitor/hippo4j-monitor-elasticsearch/src/main/java/cn/hippo4j/monitor/elasticsearch/DynamicThreadPoolElasticSearchMonitorHandler.java index 203d2457..f476ae1c 100644 --- a/hippo4j-monitor/hippo4j-monitor-elasticsearch/src/main/java/cn/hippo4j/monitor/elasticsearch/DynamicThreadPoolElasticSearchMonitorHandler.java +++ b/hippo4j-monitor/hippo4j-monitor-elasticsearch/src/main/java/cn/hippo4j/monitor/elasticsearch/DynamicThreadPoolElasticSearchMonitorHandler.java @@ -147,6 +147,7 @@ public class DynamicThreadPoolElasticSearchMonitorHandler extends AbstractDynami @Getter @Builder private static class EsIndex { + String index; String type; String mapping; 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 286db868..04f2d938 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 @@ -17,29 +17,30 @@ package cn.hippo4j.config.springboot.starter.monitor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ScheduledThreadPoolExecutor; +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.toolkit.StringUtil; import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties; import cn.hippo4j.config.springboot.starter.config.MonitorProperties; import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage; -import cn.hippo4j.common.design.builder.ThreadFactoryBuilder; import cn.hippo4j.monitor.base.DynamicThreadPoolMonitor; import cn.hippo4j.monitor.base.ThreadPoolMonitor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + import org.springframework.beans.factory.DisposableBean; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - import static cn.hippo4j.core.executor.manage.GlobalThreadPoolManage.getThreadPoolNum; /** @@ -67,7 +68,7 @@ public class ThreadPoolMonitorExecutor implements ApplicationRunner, DisposableB log.info("Start monitoring the running status of dynamic thread pool."); threadPoolMonitors = new ArrayList<>(); collectScheduledExecutor = new ScheduledThreadPoolExecutor( - new Integer(1), + 1, ThreadFactoryBuilder.builder().daemon(true).prefix("client.scheduled.collect.data").build()); // Get dynamic thread pool monitoring component. List collectTypes = Arrays.asList(monitor.getCollectTypes().split(",")); @@ -77,7 +78,7 @@ public class ThreadPoolMonitorExecutor implements ApplicationRunner, DisposableB dynamicThreadPoolMonitors.stream().filter(each -> collectTypes.contains(each.getType())).forEach(each -> threadPoolMonitors.add(each)); // Execute dynamic thread pool monitoring component. collectScheduledExecutor.scheduleWithFixedDelay( - () -> scheduleRunnable(), + this::scheduleRunnable, properties.getInitialDelay(), properties.getCollectInterval(), TimeUnit.MILLISECONDS); @@ -98,6 +99,6 @@ public class ThreadPoolMonitorExecutor implements ApplicationRunner, DisposableB @Override public void destroy() throws Exception { - Optional.ofNullable(collectScheduledExecutor).ifPresent(each -> each.shutdown()); + Optional.ofNullable(collectScheduledExecutor).ifPresent(ScheduledThreadPoolExecutor::shutdown); } }