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.
pull/1116/head
yanrongzhen 1 year ago committed by GitHub
parent 72aa732688
commit 275a8bfb92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -21,8 +21,6 @@ import cn.hippo4j.common.toolkit.StringUtil;
/**
* Http media type.
*
* @author Rongzhen Yan
*/
public final class HttpMediaType {

@ -19,8 +19,6 @@ package cn.hippo4j.common.constant;
/**
* Http method constants.
*
* @author Rongzhen Yan
*/
public class HttpMethod {

@ -19,8 +19,6 @@ package cn.hippo4j.common.constant;
/**
* Http response code.
*
* @author Rongzhen Yan
*/
public class HttpResponseCode {

@ -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
<T> BlockingQueue<T> 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
<T> BlockingQueue<T> 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
<T> BlockingQueue<T> of(Integer capacity) {
return new LinkedBlockingDeque<>(capacity);
@ -78,6 +81,7 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.SynchronousQueue}
*/
SYNCHRONOUS_QUEUE(4, "SynchronousQueue") {
@Override
<T> BlockingQueue<T> of(Integer capacity) {
return new SynchronousQueue<>();
@ -93,6 +97,7 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.LinkedTransferQueue}
*/
LINKED_TRANSFER_QUEUE(5, "LinkedTransferQueue") {
@Override
<T> BlockingQueue<T> of(Integer capacity) {
return new LinkedTransferQueue<>();
@ -108,6 +113,7 @@ public enum BlockingQueueTypeEnum {
* {@link java.util.concurrent.PriorityBlockingQueue}
*/
PRIORITY_BLOCKING_QUEUE(6, "PriorityBlockingQueue") {
@Override
<T> BlockingQueue<T> of(Integer capacity) {
return new PriorityBlockingQueue<>(capacity);
@ -123,6 +129,7 @@ public enum BlockingQueueTypeEnum {
* {@link ResizableCapacityLinkedBlockingQueue}
*/
RESIZABLE_LINKED_BLOCKING_QUEUE(9, "ResizableCapacityLinkedBlockingQueue") {
@Override
<T> BlockingQueue<T> 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 <T> BlockingQueue<T> customOrDefaultQueue(Integer capacity, Predicate<CustomBlockingQueue> predicate) {
Collection<CustomBlockingQueue> customBlockingQueues = DynamicThreadPoolServiceLoader
Collection<CustomBlockingQueue> customBlockingQueues = ServiceLoaderRegistry
.getSingletonServiceInstances(CustomBlockingQueue.class);
return customBlockingQueues.stream()

@ -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;

@ -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<CustomRejectedExecutionHandler> customRejectedExecutionHandlers = DynamicThreadPoolServiceLoader
Collection<CustomRejectedExecutionHandler> customRejectedExecutionHandlers = ServiceLoaderRegistry
.getSingletonServiceInstances(CustomRejectedExecutionHandler.class);
Optional<RejectedExecutionHandler> 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<CustomRejectedExecutionHandler> customRejectedExecutionHandlers = DynamicThreadPoolServiceLoader
Collection<CustomRejectedExecutionHandler> customRejectedExecutionHandlers = ServiceLoaderRegistry
.getSingletonServiceInstances(CustomRejectedExecutionHandler.class);
Optional<RejectedExecutionHandler> customRejected = customRejectedExecutionHandlers.stream()
.filter(each -> Objects.equals(type, each.getType()))

@ -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 {
}

@ -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 {
}

@ -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;
}

@ -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 {
}

@ -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);
}
}

@ -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<Element> extends Reducer<Element, Boolean> {
@Getter
private final Predicate<Element> predicate;
public AllMatch(@NonNull Predicate<Element> 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;
}
}

@ -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<Element> extends Reducer<Element, Boolean> {
@Getter
private final Predicate<Element> predicate;
public AnyMatch(@NonNull Predicate<Element> 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;
}
}

@ -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<Element> extends Reducer<Element, Element> {
private Predicate<Element> predicate;
public FirstOf(@NonNull Predicate<Element> 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;
}
}

@ -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<Element> extends Reducer<Element, List<Element>> {
@Override
public ReduceType reducerType() {
return ReduceType.NONE;
}
@Override
public List<Element> reduce() {
return realizations.stream().map(getCallback()).collect(Collectors.toList());
}
}

@ -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<Element, Result> {
@Getter
private Result result;
@Setter
protected IExtensionRequest request;
@Setter
protected List<IExtension> realizations;
@Setter
@Getter
private ExtensionCallback<IExtension, Element> callback;
public abstract Result reduce();
public abstract ReduceType reducerType();
public String reduceName() {
return this.getClass().getSimpleName();
}
}

@ -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 <E> Reducer<E, List<E>> none() {
return new None<>();
}
/**
* Build a FirstOf Reducer.
*
* @param predicate the condition predicate.
* @return FirstOf Policy Reducer.
*/
public static <E> Reducer<E, E> firstOf(@NonNull Predicate<E> predicate) {
return new FirstOf<>(predicate);
}
/**
* Build a FirstOf Not-null Reducer.
*
* @return FirstOf Not-null Policy Reducer.
*/
public static <E> Reducer<E, E> firstOfNotNull() {
return new FirstOf<>(Objects::nonNull);
}
/**
* Build a AnyMatch Reducer.
*
* @param predicate the condition predicate.
* @return AnyMatch Policy Reducer.
*/
public static <E> Reducer<E, Boolean> anyMatch(Predicate<E> predicate) {
return new AnyMatch<>(predicate);
}
/**
* Build a AllMatch Reducer
*
* @param predicate the condition predicate.
* @return AllMatch Policy Reducer.
*/
public static <E> Reducer<E, Boolean> allMatch(@NonNull Predicate<E> predicate) {
return new AllMatch<>(predicate);
}
}

@ -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();
}
}

@ -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 <T>
* @param <R>
*/
@FunctionalInterface
public interface ExtensionCallback<T, R> extends Function<T, R> {
R apply(T extension);
}

@ -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 <T extends IExtension, E> List<E> reduceExecute(Class<T> targetClz,
ExtensionCallback<T, E> callback) {
return reduceExecute(targetClz, callback, Reducers.none());
}
@SuppressWarnings("unchecked")
public static <T extends IExtension, E, R> R reduceExecute(Class<T> targetClz,
ExtensionCallback<T, E> callback,
Reducer<E, R> reducer) {
Assert.isTrue(IExtension.class.isAssignableFrom(targetClz),
"can not execute extension point. please implement base extension interface(" + IExtension.class.getName() + ") first.");
List<IExtension> 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<IExtension, E>) callback);
return reducer.reduce();
}
}

@ -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<Class<? extends IExtension>, List<IExtension>> 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<IExtension>) intf, realization);
}
}
}
private void register(Class<? extends IExtension> extension, IExtension realization) {
if (!registry.containsKey(extension) || CollectionUtil.isEmpty(registry.get(extension))) {
List<IExtension> 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<IExtension> realizations = registry.get(extension);
realizations.add(realization);
registry.put(extension, realizations);
}
}
@Override
public List<IExtension> find(Class<? extends IExtension> extension) {
return registry.get(extension);
}
}

@ -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<IExtension> find(Class<? extends IExtension> extension);
}

@ -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
}

@ -15,7 +15,7 @@
* limitations under the License.
*/
package cn.hippo4j.common.spi;
package cn.hippo4j.common.extension.support;
/**
* Service loader instantiation exception.

@ -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<Class<?>, Collection<?>> SERVICES = new ConcurrentHashMap<>();
private DynamicThreadPoolServiceLoader() {
private ServiceLoaderRegistry() {
}
/**

@ -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);

@ -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;
}
}

@ -43,8 +43,6 @@ import static cn.hippo4j.common.constant.HttpHeaderConstants.CONTENT_LENGTH;
/**
* Http request utilities.
*
* @author Rongzhen Yan
*/
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)

@ -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 {

@ -28,8 +28,6 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* Log message.
*
* @author Rongzhen Yan
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LogMessage {

@ -0,0 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.hippo4j.common.extension.support.ExtensionAutoConfiguration

@ -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<Integer> 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);
}
}

@ -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;
}
}

@ -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;
}
}

@ -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);
}

@ -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;
}
}

@ -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;
}
}

@ -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);
}

@ -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();
}

@ -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;
}
}

@ -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<TestSingletonInterfaceSPI> instances = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class);
ServiceLoaderRegistry.register(TestSingletonInterfaceSPI.class);
Collection<TestSingletonInterfaceSPI> 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<TestSingletonInterfaceSPI> instances = DynamicThreadPoolServiceLoader.newServiceInstances(TestSingletonInterfaceSPI.class);
ServiceLoaderRegistry.register(TestSingletonInterfaceSPI.class);
Collection<TestSingletonInterfaceSPI> 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<TestSingletonInterfaceSPI> instances = DynamicThreadPoolServiceLoader.getServiceInstances(TestSingletonInterfaceSPI.class);
assertThat(instances.iterator().next(), is(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestSingletonInterfaceSPI.class).iterator().next()));
ServiceLoaderRegistry.register(TestSingletonInterfaceSPI.class);
Collection<TestSingletonInterfaceSPI> 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<TestInterfaceSPI> instances = DynamicThreadPoolServiceLoader.getServiceInstances(TestInterfaceSPI.class);
assertThat(instances.iterator().next(), not(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(TestInterfaceSPI.class).iterator().next()));
ServiceLoaderRegistry.register(TestInterfaceSPI.class);
Collection<TestInterfaceSPI> instances = ServiceLoaderRegistry.getServiceInstances(TestInterfaceSPI.class);
assertThat(instances.iterator().next(), not(ServiceLoaderRegistry.getSingletonServiceInstances(TestInterfaceSPI.class).iterator().next()));
}
}

@ -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 {
}

@ -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 {
}

@ -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 {

@ -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 {
}

@ -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<DynamicThreadPoolAdapterSPI> instances = DynamicThreadPoolServiceLoader.getSingletonServiceInstances(DynamicThreadPoolAdapterSPI.class);
ServiceLoaderRegistry.register(DynamicThreadPoolAdapterSPI.class);
Collection<DynamicThreadPoolAdapterSPI> instances = ServiceLoaderRegistry.getSingletonServiceInstances(DynamicThreadPoolAdapterSPI.class);
if (CollectionUtil.isEmpty(instances)) {
return;
}

@ -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;

@ -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<String> collectTypes = Arrays.asList(monitor.getCollectTypes().split(","));
ApplicationContextHolder.getBeansOfType(ThreadPoolMonitor.class).forEach((beanName, bean) -> threadPoolMonitors.add(bean));
Collection<DynamicThreadPoolMonitor> 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(

@ -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) {

@ -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<ThreadPoolMonitor> dynamicThreadPoolMonitors =
DynamicThreadPoolServiceLoader.getSingletonServiceInstances(ThreadPoolMonitor.class);
ServiceLoaderRegistry.getSingletonServiceInstances(ThreadPoolMonitor.class);
Map<String, ThreadPoolMonitor> threadPoolMonitorMap = ApplicationContextHolder.getBeansOfType(ThreadPoolMonitor.class);
boolean customerDynamicThreadPoolMonitorFlag = CollectionUtil.isNotEmpty(dynamicThreadPoolMonitors) || CollectionUtil.isNotEmpty(threadPoolMonitorMap);
if (customerDynamicThreadPoolMonitorFlag) {

@ -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())

Loading…
Cancel
Save