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/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/extension/config/ExtensionRegisterBootstrap.java b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/config/ExtensionRegisterBootstrap.java new file mode 100644 index 00000000..1b523ad6 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/config/ExtensionRegisterBootstrap.java @@ -0,0 +1,64 @@ +/* + * 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.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; + +/** + * 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 { + + Map realizationBeanMap = applicationContext.getBeansWithAnnotation(Realization.class); + realizationBeanMap.values().forEach( + realization -> { + if (isInfrastructureClass(realization)) { + return; + } + if (realization instanceof IExtension) { + registry.register((IExtension) realization); + } + }); + } + + private boolean isInfrastructureClass(Object obj) { + return obj.getClass().isAssignableFrom(IExtension.class); + } +} 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..3ad68b74 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/AllMatch.java @@ -0,0 +1,62 @@ +/* + * 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; + setResult(true); + } + + @Override + public Boolean reduce() { + if (CollectionUtil.isEmpty(extensionImplementations)) { + return false; + } else { + for (IExtension extensionImpl : extensionImplementations) { + if (!predicate.test(getCallback().apply(extensionImpl))) { + 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..dfc00c17 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/AnyMatch.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; + +/** + * 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; + this.setResult(false); + } + + @Override + public Boolean reduce() { + if (CollectionUtil.isEmpty(extensionImplementations)) { + return false; + } + for (IExtension extension : extensionImplementations) { + 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..c8ad2558 --- /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 : extensionImplementations) { + 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..6b1d2ad5 --- /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 extensionImplementations.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..f039d3e8 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/reducer/Reducer.java @@ -0,0 +1,64 @@ +/* + * 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 boolean hasBreak = false; + + @Getter + private Result result; + + @Setter + protected IExtensionRequest request; + + @Setter + protected List extensionImplementations; + + @Setter + @Getter + private ExtensionCallback callback; + + public abstract Result reduce(); + + public boolean willBreak() { + return false; + } + + public void setResult(Result result) { + this.result = result; + } + + 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..3e0eb614 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/extension/support/ExtensionInvoker.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.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.spi.DynamicThreadPoolServiceLoader; +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 implementations = registry.find(targetClz); + if (CollectionUtil.isEmpty(implementations)) { + implementations = new ArrayList<>(DynamicThreadPoolServiceLoader.getSingletonServiceInstances(targetClz)); + } + Assert.notEmpty(implementations, "can not find any extension realizations with interface: " + targetClz.getName()); + + reducer.setExtensionImplementations(implementations); + 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..882c9d3b --- /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 implementation) { + + Class implClass = implementation.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, implementation); + } + } + } + + private void register(Class extension, IExtension realization) { + if (!registry.containsKey(extension) || CollectionUtil.isEmpty(registry.get(extension))) { + List implementations = new ArrayList<>(); + implementations.add(realization); + registry.put(extension, implementations); + } else { + if (registry.get(extension).contains(realization)) { + log.warn(LogMessage.getInstance() + .kv("realizationClassName", realization.getClass().getName()) + .msg("Extension realization already registered, skip.")); + } + List implementations = registry.get(extension); + implementations.add(realization); + registry.put(extension, implementations); + } + } + + @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/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..16e9f602 --- /dev/null +++ b/hippo4j-common/src/test/java/cn/hippo4j/common/extension/ExtensionInvokerTest.java @@ -0,0 +1,84 @@ +/* + * 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.spi.DynamicThreadPoolServiceLoader; +import org.assertj.core.util.Lists; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +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()); + + DynamicThreadPoolServiceLoader.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/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