mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
f504a176e4
commit
3b53230a38
@ -2,7 +2,7 @@
|
||||
<a href="https://hutool.cn/"><img src="https://plus.hutool.cn/images/hutool.svg" width="45%"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<strong>🍬A set of tools that keep Java sweet.</strong>
|
||||
<strong>🍬Make Java Sweet Again.</strong>
|
||||
</p>
|
||||
<p align="center">
|
||||
👉 <a href="https://hutool.cn">https://hutool.cn/</a> 👈
|
||||
|
@ -2,7 +2,7 @@
|
||||
<a href="https://hutool.cn/"><img src="https://plus.hutool.cn/images/hutool.svg" width="45%"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<strong>🍬A set of tools that keep Java sweet.</strong>
|
||||
<strong>🍬Make Java Sweet Again.</strong>
|
||||
</p>
|
||||
<p align="center">
|
||||
👉 <a href="https://hutool.cn">https://hutool.cn/</a> 👈
|
||||
|
@ -34,7 +34,7 @@ import java.util.ServiceLoader;
|
||||
* @author looly
|
||||
* @since 5.1.6
|
||||
*/
|
||||
public class ServiceLoaderUtil {
|
||||
public class JdkServiceLoaderUtil {
|
||||
|
||||
/**
|
||||
* 。加载第一个可用服务,如果用户定义了多个接口实现类,只获取第一个不报错的服务
|
@ -20,8 +20,7 @@ import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.AccessUtil;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.Properties;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 键值对服务加载器,使用{@link Properties}加载并存储服务
|
||||
@ -75,6 +74,7 @@ public class KVServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
// endregion
|
||||
|
||||
private Properties serviceProperties;
|
||||
// key: serviceName, value: service instance
|
||||
private final SimpleCache<String, S> serviceCache;
|
||||
|
||||
/**
|
||||
@ -136,6 +136,24 @@ public class KVServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
return this.serviceCache.get(serviceName, () -> createService(serviceName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<S> iterator() {
|
||||
return new Iterator<S>() {
|
||||
private final Iterator<String> nameIter =
|
||||
serviceProperties.stringPropertyNames().iterator();
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return nameIter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public S next() {
|
||||
return getService(nameIter.next());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// region ----- private methods
|
||||
/**
|
||||
* 创建服务,无缓存
|
||||
*
|
||||
@ -161,4 +179,5 @@ public class KVServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
|
||||
return ClassLoaderUtil.loadClass(serviceClassName);
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
@ -13,21 +13,33 @@
|
||||
package org.dromara.hutool.core.spi;
|
||||
|
||||
import org.dromara.hutool.core.cache.SimpleCache;
|
||||
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
import org.dromara.hutool.core.io.resource.MultiResource;
|
||||
import org.dromara.hutool.core.io.resource.Resource;
|
||||
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.AccessUtil;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 列表类型的服务加载器,用于替换JDK提供的{@link java.util.ServiceLoader}
|
||||
* 列表类型的服务加载器,用于替换JDK提供的{@link java.util.ServiceLoader}<br>
|
||||
* 相比JDK,增加了:
|
||||
* <ul>
|
||||
* <li>可选服务存储位置(默认位于META-INF/services/)。</li>
|
||||
* <li>可自定义编码。</li>
|
||||
* <li>可自定义加载指定的服务实例。</li>
|
||||
* <li>可自定义加载指定的服务类,由用户决定如何实例化(如传入自定义构造参数等)。</li>
|
||||
* <li>提供更加灵活的服务加载机制,当选择加载指定服务时,其它服务无需加载。</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <S> 服务类型
|
||||
* @author looly
|
||||
@ -78,6 +90,7 @@ public class ListServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
// endregion
|
||||
|
||||
private final List<String> serviceNames;
|
||||
// key: className, value: service instance
|
||||
private final SimpleCache<String, S> serviceCache;
|
||||
|
||||
/**
|
||||
@ -114,6 +127,48 @@ public class ListServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
return this.serviceNames.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定服务的实现类
|
||||
*
|
||||
* @param index 服务名称
|
||||
* @return 服务名称对应的实现类
|
||||
*/
|
||||
public Class<S> getServiceClass(final int index) {
|
||||
return AccessUtil.doPrivileged(() -> getServiceClassUnsafe(index), this.acc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定序号对应的服务,使用缓存,多次调用只返回相同的服务对象
|
||||
*
|
||||
* @param index 服务名称
|
||||
* @return 服务对象
|
||||
*/
|
||||
public S getService(final int index) {
|
||||
final String serviceClassName = this.serviceNames.get(index);
|
||||
if(null == serviceClassName){
|
||||
return null;
|
||||
}
|
||||
return getServiceByName(serviceClassName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<S> iterator() {
|
||||
return new Iterator<S>() {
|
||||
private final Iterator<String> nameIter = serviceNames.iterator();
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return nameIter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public S next() {
|
||||
return getServiceByName(nameIter.next());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// region ----- private methods
|
||||
|
||||
/**
|
||||
* 解析一个资源,一个资源对应一个service文件
|
||||
*
|
||||
@ -165,12 +220,21 @@ public class ListServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
return lineNo + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查行
|
||||
*
|
||||
* @param resource 资源
|
||||
* @param lineNo 行号
|
||||
* @param line 行内容
|
||||
*/
|
||||
private void checkLine(final Resource resource, final int lineNo, final String line) {
|
||||
if (StrUtil.containsBlank(line)) {
|
||||
// 类中不允许空白符
|
||||
fail(resource, lineNo, "Illegal configuration-file syntax");
|
||||
}
|
||||
int cp = line.codePointAt(0);
|
||||
if (!Character.isJavaIdentifierStart(cp)) {
|
||||
// 非Java合法标识符
|
||||
fail(resource, lineNo, "Illegal provider-class name: " + line);
|
||||
}
|
||||
final int n = line.length();
|
||||
@ -182,8 +246,52 @@ public class ListServiceLoader<S> extends AbsServiceLoader<S> {
|
||||
}
|
||||
}
|
||||
|
||||
private void fail(final Resource resource, final int line, final String msg) {
|
||||
throw new SPIException(this.serviceClass + ":" + resource.getUrl() + ":" + line + ": " + msg);
|
||||
/**
|
||||
* 抛出异常
|
||||
*
|
||||
* @param resource 资源
|
||||
* @param lineNo 行号
|
||||
* @param msg 消息
|
||||
*/
|
||||
private void fail(final Resource resource, final int lineNo, final String msg) {
|
||||
throw new SPIException(this.serviceClass + ":" + resource.getUrl() + ":" + lineNo + ": " + msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定class名对应的服务,使用缓存,多次调用只返回相同的服务对象
|
||||
*
|
||||
* @param serviceClassName 服务名称
|
||||
* @return 服务对象
|
||||
*/
|
||||
private S getServiceByName(final String serviceClassName) {
|
||||
return this.serviceCache.get(serviceClassName, () -> createService(serviceClassName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建服务,无缓存
|
||||
*
|
||||
* @param serviceClassName 服务类名称
|
||||
* @return 服务对象
|
||||
*/
|
||||
private S createService(final String serviceClassName) {
|
||||
return AccessUtil.doPrivileged(() ->
|
||||
ConstructorUtil.newInstance(ClassLoaderUtil.loadClass(serviceClassName)),
|
||||
this.acc);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定服务的实现类
|
||||
*
|
||||
* @param index 服务索引号
|
||||
* @return 服务名称对应的实现类
|
||||
*/
|
||||
private Class<S> getServiceClassUnsafe(final int index) {
|
||||
final String serviceClassName = this.serviceNames.get(index);
|
||||
if (StrUtil.isBlank(serviceClassName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ClassLoaderUtil.loadClass(serviceClassName);
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
@ -16,10 +16,10 @@ package org.dromara.hutool.core.spi;
|
||||
* SPI服务加载接口<br>
|
||||
* 用户实现此接口用于制定不同的服务加载方式
|
||||
*
|
||||
* @param <T> 服务对象类型
|
||||
* @param <S> 服务对象类型
|
||||
* @author looly
|
||||
*/
|
||||
public interface ServiceLoader<T> {
|
||||
public interface ServiceLoader<S> extends Iterable<S>{
|
||||
|
||||
/**
|
||||
* 加载服务
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2023 looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.spi;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* 服务提供接口SPI(Service Provider interface)相关工具类
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class SpiUtil {
|
||||
|
||||
/**
|
||||
* 加载第一个可用服务,如果用户定义了多个接口实现类,只获取第一个不报错的服务
|
||||
*
|
||||
* @param <T> 接口类型
|
||||
* @param clazz 服务接口
|
||||
* @return 第一个服务接口实现对象,无实现返回{@code null}
|
||||
*/
|
||||
public static <T> T loadFirstAvailable(final Class<T> clazz) {
|
||||
final Iterator<T> iterator = loadList(clazz).iterator();
|
||||
while (iterator.hasNext()) {
|
||||
try {
|
||||
return iterator.next();
|
||||
} catch (final Throwable ignore) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载服务
|
||||
*
|
||||
* @param <T> 接口类型
|
||||
* @param clazz 服务接口
|
||||
* @return 服务接口实现列表
|
||||
*/
|
||||
public static <T> ServiceLoader<T> loadList(final Class<T> clazz) {
|
||||
return loadList(clazz, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载服务
|
||||
*
|
||||
* @param <T> 接口类型
|
||||
* @param clazz 服务接口
|
||||
* @param loader {@link ClassLoader}
|
||||
* @return 服务接口实现列表
|
||||
*/
|
||||
public static <T> ServiceLoader<T> loadList(final Class<T> clazz, final ClassLoader loader) {
|
||||
return ListServiceLoader.of(clazz, loader);
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
|
||||
package org.dromara.hutool.crypto.provider;
|
||||
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.crypto.SecureUtil;
|
||||
|
||||
import java.security.Provider;
|
||||
@ -54,7 +54,7 @@ public class GlobalProviderFactory {
|
||||
* @return {@link Provider} or {@code null}
|
||||
*/
|
||||
private static Provider _createProvider() {
|
||||
final ProviderFactory factory = ServiceLoaderUtil.loadFirstAvailable(ProviderFactory.class);
|
||||
final ProviderFactory factory = SpiUtil.loadFirstAvailable(ProviderFactory.class);
|
||||
if (null == factory) {
|
||||
return null;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
package org.dromara.hutool.extra.aop.proxy;
|
||||
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.extra.aop.aspects.Aspect;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -56,7 +56,7 @@ public interface ProxyFactory extends Serializable {
|
||||
* @return 代理工厂
|
||||
*/
|
||||
static ProxyFactory of() {
|
||||
return ServiceLoaderUtil.loadFirstAvailable(ProxyFactory.class);
|
||||
return SpiUtil.loadFirstAvailable(ProxyFactory.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,12 +13,11 @@
|
||||
package org.dromara.hutool.extra.expression.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.log.StaticLog;
|
||||
|
||||
import org.dromara.hutool.extra.expression.ExpressionEngine;
|
||||
import org.dromara.hutool.extra.expression.ExpressionException;
|
||||
import org.dromara.hutool.log.StaticLog;
|
||||
|
||||
/**
|
||||
* 表达式语言引擎工厂类,用于根据用户引入的表达式jar,自动创建对应的引擎对象
|
||||
@ -56,7 +55,7 @@ public class ExpressionFactory {
|
||||
* @return {@link ExpressionEngine}
|
||||
*/
|
||||
private static ExpressionEngine doCreate() {
|
||||
final ExpressionEngine engine = ServiceLoaderUtil.loadFirstAvailable(ExpressionEngine.class);
|
||||
final ExpressionEngine engine = SpiUtil.loadFirstAvailable(ExpressionEngine.class);
|
||||
if(null != engine){
|
||||
return engine;
|
||||
}
|
||||
|
@ -13,12 +13,11 @@
|
||||
package org.dromara.hutool.extra.pinyin.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.log.StaticLog;
|
||||
|
||||
import org.dromara.hutool.extra.pinyin.PinyinEngine;
|
||||
import org.dromara.hutool.extra.pinyin.PinyinException;
|
||||
import org.dromara.hutool.log.StaticLog;
|
||||
|
||||
/**
|
||||
* 简单拼音引擎工厂,用于根据用户引入的拼音库jar,自动创建对应的拼音引擎对象
|
||||
@ -55,7 +54,7 @@ public class PinyinFactory {
|
||||
* @return {@link PinyinEngine}
|
||||
*/
|
||||
private static PinyinEngine doCreate() {
|
||||
final PinyinEngine engine = ServiceLoaderUtil.loadFirstAvailable(PinyinEngine.class);
|
||||
final PinyinEngine engine = SpiUtil.loadFirstAvailable(PinyinEngine.class);
|
||||
if(null != engine){
|
||||
return engine;
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ package org.dromara.hutool.extra.template.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.extra.template.TemplateConfig;
|
||||
import org.dromara.hutool.extra.template.TemplateEngine;
|
||||
import org.dromara.hutool.extra.template.TemplateException;
|
||||
@ -75,7 +75,7 @@ public class TemplateFactory {
|
||||
if(null != customEngineClass){
|
||||
engine = ConstructorUtil.newInstance(customEngineClass);
|
||||
}else{
|
||||
engine = ServiceLoaderUtil.loadFirstAvailable(TemplateEngine.class);
|
||||
engine = SpiUtil.loadFirstAvailable(TemplateEngine.class);
|
||||
}
|
||||
if(null != engine){
|
||||
return engine.init(config);
|
||||
|
@ -13,7 +13,7 @@
|
||||
package org.dromara.hutool.extra.tokenizer.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.extra.tokenizer.TokenizerEngine;
|
||||
import org.dromara.hutool.extra.tokenizer.TokenizerException;
|
||||
@ -55,7 +55,7 @@ public class TokenizerFactory {
|
||||
* @return {@link TokenizerEngine}
|
||||
*/
|
||||
private static TokenizerEngine doCreate() {
|
||||
final TokenizerEngine engine = ServiceLoaderUtil.loadFirstAvailable(TokenizerEngine.class);
|
||||
final TokenizerEngine engine = SpiUtil.loadFirstAvailable(TokenizerEngine.class);
|
||||
if(null != engine){
|
||||
return engine;
|
||||
}
|
||||
|
@ -13,8 +13,8 @@
|
||||
package org.dromara.hutool.http.client.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.http.HttpException;
|
||||
import org.dromara.hutool.http.client.ClientConfig;
|
||||
import org.dromara.hutool.http.client.ClientEngine;
|
||||
@ -68,7 +68,7 @@ public class ClientEngineFactory {
|
||||
* @return {@code EngineFactory}
|
||||
*/
|
||||
private static ClientEngine doCreate() {
|
||||
final ClientEngine engine = ServiceLoaderUtil.loadFirstAvailable(ClientEngine.class);
|
||||
final ClientEngine engine = SpiUtil.loadFirstAvailable(ClientEngine.class);
|
||||
if (null != engine) {
|
||||
return engine;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ package org.dromara.hutool.log;
|
||||
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
||||
import org.dromara.hutool.core.lang.caller.CallerUtil;
|
||||
import org.dromara.hutool.core.map.SafeConcurrentHashMap;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.SpiUtil;
|
||||
import org.dromara.hutool.log.engine.console.ConsoleLogFactory;
|
||||
import org.dromara.hutool.log.engine.jdk.JdkLogFactory;
|
||||
|
||||
@ -182,7 +182,7 @@ public abstract class LogFactory {
|
||||
* @return 日志实现类
|
||||
*/
|
||||
private static LogFactory doCreate() {
|
||||
final LogFactory factory = ServiceLoaderUtil.loadFirstAvailable(LogFactory.class);
|
||||
final LogFactory factory = SpiUtil.loadFirstAvailable(LogFactory.class);
|
||||
if (null != factory) {
|
||||
return factory;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user