001/* 002 * Copyright 2024-2025, Warm-Flow (290631660@qq.com). 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.dromara.warm.flow.core.utils; 017 018import java.security.AccessController; 019import java.security.PrivilegedAction; 020import java.util.*; 021 022/** 023 * SPI机制中的服务加载工具类 024 * 025 * @author warm 026 */ 027public class ServiceLoaderUtil { 028 029 /** 030 * 。加载第一个可用服务,如果用户定义了多个接口实现类,只获取第一个不报错的服务 031 * 032 * @param <T> 接口类型 033 * @param clazz 服务接口 034 * @return 第一个服务接口实现对象,无实现返回{@code null} 035 */ 036 public static <T> T loadFirst(Class<T> clazz) { 037 final Iterator<T> iterator = load(clazz).iterator(); 038 while (iterator.hasNext()) { 039 try { 040 return iterator.next(); 041 } catch (ServiceConfigurationError ignore) { 042 043 } 044 } 045 return null; 046 } 047 048 /** 049 * 加载服务 并已list列表返回 050 * 051 * @param <T> 接口类型 052 * @param clazz 服务接口 053 * @return 服务接口实现列表 054 * @since 5.4.2 055 */ 056 public static <T> List<T> loadList(Class<T> clazz) { 057 List<T> list = new ArrayList<>(); 058 ServiceLoader<T> serviceLoader = load(clazz); 059 Iterator<T> serviceIterator = serviceLoader.iterator(); 060 while (serviceIterator.hasNext()) { 061 try { 062 list.add(serviceIterator.next()); 063 } catch (ServiceConfigurationError ignore) { 064 065 } 066 } 067 return list; 068 } 069 070 /** 071 * 加载服务 072 * 073 * @param <T> 接口类型 074 * @param clazz 服务接口 075 * @return 服务接口实现列表 076 */ 077 public static <T> ServiceLoader<T> load(Class<T> clazz) { 078 return load(clazz, null); 079 } 080 081 /** 082 * 加载服务 083 * 084 * @param <T> 接口类型 085 * @param clazz 服务接口 086 * @param loader {@link ClassLoader} 087 * @return 服务接口实现列表 088 */ 089 public static <T> ServiceLoader<T> load(Class<T> clazz, ClassLoader loader) { 090 return ServiceLoader.load(clazz, ObjectUtil.defaultIfNull(loader, ServiceLoaderUtil::getClassLoader)); 091 } 092 093 /** 094 * 获取{@link ClassLoader}<br> 095 * 获取顺序如下:<br> 096 * 097 * <pre> 098 * 1、获取当前线程的ContextClassLoader 099 * 2、获取当前类对应的ClassLoader 100 * 3、获取系统ClassLoader({@link ClassLoader#getSystemClassLoader()}) 101 * </pre> 102 * 103 * @return 类加载器 104 */ 105 public static ClassLoader getClassLoader() { 106 ClassLoader classLoader = getContextClassLoader(); 107 if (classLoader == null) { 108 classLoader = ServiceLoaderUtil.class.getClassLoader(); 109 if (null == classLoader) { 110 classLoader = getSystemClassLoader(); 111 } 112 } 113 return classLoader; 114 } 115 116 /** 117 * 获取当前线程的{@link ClassLoader} 118 * 119 * @return 当前线程的class loader 120 * @see Thread#getContextClassLoader() 121 */ 122 public static ClassLoader getContextClassLoader() { 123 if (System.getSecurityManager() == null) { 124 return Thread.currentThread().getContextClassLoader(); 125 } else { 126 // 绕开权限检查 127 return AccessController.doPrivileged( 128 (PrivilegedAction<ClassLoader>) () -> Thread.currentThread().getContextClassLoader()); 129 } 130 } 131 132 /** 133 * 获取系统{@link ClassLoader} 134 * 135 * @return 系统{@link ClassLoader} 136 * @see ClassLoader#getSystemClassLoader() 137 * @since 5.7.0 138 */ 139 public static ClassLoader getSystemClassLoader() { 140 if (System.getSecurityManager() == null) { 141 return ClassLoader.getSystemClassLoader(); 142 } else { 143 // 绕开权限检查 144 return AccessController.doPrivileged( 145 (PrivilegedAction<ClassLoader>) ClassLoader::getSystemClassLoader); 146 } 147 } 148 149}