mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add setClassLoader
This commit is contained in:
parent
1ddc01453f
commit
476285b302
@ -8,6 +8,7 @@
|
|||||||
### 新特性
|
### 新特性
|
||||||
* 【all】 修复注释中的错别字(issue#I12XE6@Gitee)
|
* 【all】 修复注释中的错别字(issue#I12XE6@Gitee)
|
||||||
* 【core】 CsvWriter支持其它类型的参数(issue#I12XE3@Gitee)
|
* 【core】 CsvWriter支持其它类型的参数(issue#I12XE3@Gitee)
|
||||||
|
* 【core】 ClassScaner支持自定义ClassLoader
|
||||||
|
|
||||||
### Bug修复
|
### Bug修复
|
||||||
* 【all】 修复阶乘计算错误bug(issue#I12XE4@Gitee)
|
* 【all】 修复阶乘计算错误bug(issue#I12XE4@Gitee)
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
package cn.hutool.core.lang;
|
package cn.hutool.core.lang;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.collection.EnumerationIter;
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
|
import cn.hutool.core.io.resource.ResourceUtil;
|
||||||
|
import cn.hutool.core.util.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -12,48 +19,54 @@ import java.util.Set;
|
|||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.collection.EnumerationIter;
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
|
||||||
import cn.hutool.core.io.IORuntimeException;
|
|
||||||
import cn.hutool.core.io.resource.ResourceUtil;
|
|
||||||
import cn.hutool.core.util.CharUtil;
|
|
||||||
import cn.hutool.core.util.CharsetUtil;
|
|
||||||
import cn.hutool.core.util.ClassUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.hutool.core.util.URLUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类扫描器
|
* 类扫描器
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
* @since 4.1.5
|
* @since 4.1.5
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class ClassScaner implements Serializable{
|
public class ClassScaner implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/** 包名 */
|
/**
|
||||||
|
* 包名
|
||||||
|
*/
|
||||||
private String packageName;
|
private String packageName;
|
||||||
/** 包名,最后跟一个点,表示包名,避免在检查前缀时的歧义 */
|
/**
|
||||||
|
* 包名,最后跟一个点,表示包名,避免在检查前缀时的歧义
|
||||||
|
*/
|
||||||
private String packageNameWithDot;
|
private String packageNameWithDot;
|
||||||
/** 包路径,用于文件中对路径操作 */
|
/**
|
||||||
|
* 包路径,用于文件中对路径操作
|
||||||
|
*/
|
||||||
private String packageDirName;
|
private String packageDirName;
|
||||||
/** 包路径,用于jar中对路径操作,在Linux下与packageDirName一致 */
|
/**
|
||||||
|
* 包路径,用于jar中对路径操作,在Linux下与packageDirName一致
|
||||||
|
*/
|
||||||
private String packagePath;
|
private String packagePath;
|
||||||
/** 过滤器 */
|
/**
|
||||||
|
* 过滤器
|
||||||
|
*/
|
||||||
private Filter<Class<?>> classFilter;
|
private Filter<Class<?>> classFilter;
|
||||||
/** 编码 */
|
/**
|
||||||
|
* 编码
|
||||||
|
*/
|
||||||
private Charset charset;
|
private Charset charset;
|
||||||
/** 是否初始化类 */
|
/**
|
||||||
|
* 类加载器
|
||||||
|
*/
|
||||||
|
private ClassLoader classLoader;
|
||||||
|
/**
|
||||||
|
* 是否初始化类
|
||||||
|
*/
|
||||||
private boolean initialize;
|
private boolean initialize;
|
||||||
|
|
||||||
private Set<Class<?>> classes = new HashSet<Class<?>>();
|
private Set<Class<?>> classes = new HashSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 扫描指定包路径下所有包含指定注解的类
|
* 扫描指定包路径下所有包含指定注解的类
|
||||||
*
|
*
|
||||||
* @param packageName 包路径
|
* @param packageName 包路径
|
||||||
* @param annotationClass 注解类
|
* @param annotationClass 注解类
|
||||||
* @return 类集合
|
* @return 类集合
|
||||||
*/
|
*/
|
||||||
@ -70,7 +83,7 @@ public class ClassScaner implements Serializable{
|
|||||||
* 扫描指定包路径下所有指定类或接口的子类或实现类
|
* 扫描指定包路径下所有指定类或接口的子类或实现类
|
||||||
*
|
*
|
||||||
* @param packageName 包路径
|
* @param packageName 包路径
|
||||||
* @param superClass 父类或接口
|
* @param superClass 父类或接口
|
||||||
* @return 类集合
|
* @return 类集合
|
||||||
*/
|
*/
|
||||||
public static Set<Class<?>> scanPackageBySuper(String packageName, final Class<?> superClass) {
|
public static Set<Class<?>> scanPackageBySuper(String packageName, final Class<?> superClass) {
|
||||||
@ -145,7 +158,7 @@ public class ClassScaner implements Serializable{
|
|||||||
*
|
*
|
||||||
* @param packageName 包名,所有包传入""或者null
|
* @param packageName 包名,所有包传入""或者null
|
||||||
* @param classFilter 过滤器,无需传入null
|
* @param classFilter 过滤器,无需传入null
|
||||||
* @param charset 编码
|
* @param charset 编码
|
||||||
*/
|
*/
|
||||||
public ClassScaner(String packageName, Filter<Class<?>> classFilter, Charset charset) {
|
public ClassScaner(String packageName, Filter<Class<?>> classFilter, Charset charset) {
|
||||||
packageName = StrUtil.nullToEmpty(packageName);
|
packageName = StrUtil.nullToEmpty(packageName);
|
||||||
@ -165,16 +178,16 @@ public class ClassScaner implements Serializable{
|
|||||||
public Set<Class<?>> scan() {
|
public Set<Class<?>> scan() {
|
||||||
for (URL url : ResourceUtil.getResourceIter(this.packagePath)) {
|
for (URL url : ResourceUtil.getResourceIter(this.packagePath)) {
|
||||||
switch (url.getProtocol()) {
|
switch (url.getProtocol()) {
|
||||||
case "file":
|
case "file":
|
||||||
scanFile(new File(URLUtil.decode(url.getFile(), this.charset.name())), null);
|
scanFile(new File(URLUtil.decode(url.getFile(), this.charset.name())), null);
|
||||||
break;
|
break;
|
||||||
case "jar":
|
case "jar":
|
||||||
scanJar(URLUtil.getJarFile(url));
|
scanJar(URLUtil.getJarFile(url));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CollUtil.isEmpty(this.classes)) {
|
if (CollUtil.isEmpty(this.classes)) {
|
||||||
scanJavaClassPaths();
|
scanJavaClassPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,11 +203,20 @@ public class ClassScaner implements Serializable{
|
|||||||
this.initialize = initialize;
|
this.initialize = initialize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置自定义的类加载器
|
||||||
|
*
|
||||||
|
* @param classLoader 类加载器
|
||||||
|
* @since 4.6.9
|
||||||
|
*/
|
||||||
|
public void setClassLoader(ClassLoader classLoader) {
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------- Private method start
|
// --------------------------------------------------------------------------------------------------- Private method start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 扫描Java指定的ClassPath路径
|
* 扫描Java指定的ClassPath路径
|
||||||
*
|
|
||||||
* @return 扫描到的类
|
|
||||||
*/
|
*/
|
||||||
private void scanJavaClassPaths() {
|
private void scanJavaClassPaths() {
|
||||||
final String[] javaClassPaths = ClassUtil.getJavaClassPaths();
|
final String[] javaClassPaths = ClassUtil.getJavaClassPaths();
|
||||||
@ -209,7 +231,7 @@ public class ClassScaner implements Serializable{
|
|||||||
/**
|
/**
|
||||||
* 扫描文件或目录中的类
|
* 扫描文件或目录中的类
|
||||||
*
|
*
|
||||||
* @param file 文件或目录
|
* @param file 文件或目录
|
||||||
* @param rootDir 包名对应classpath绝对路径
|
* @param rootDir 包名对应classpath绝对路径
|
||||||
*/
|
*/
|
||||||
private void scanFile(File file, String rootDir) {
|
private void scanFile(File file, String rootDir) {
|
||||||
@ -263,9 +285,15 @@ public class ClassScaner implements Serializable{
|
|||||||
* @return 加载的类
|
* @return 加载的类
|
||||||
*/
|
*/
|
||||||
private Class<?> loadClass(String className) {
|
private Class<?> loadClass(String className) {
|
||||||
|
ClassLoader loader = this.classLoader;
|
||||||
|
if (null == loader) {
|
||||||
|
loader = ClassLoaderUtil.getClassLoader();
|
||||||
|
this.classLoader = loader;
|
||||||
|
}
|
||||||
|
|
||||||
Class<?> clazz = null;
|
Class<?> clazz = null;
|
||||||
try {
|
try {
|
||||||
clazz = Class.forName(className, this.initialize, ClassUtil.getClassLoader());
|
clazz = Class.forName(className, this.initialize, loader);
|
||||||
} catch (NoClassDefFoundError e) {
|
} catch (NoClassDefFoundError e) {
|
||||||
// 由于依赖库导致的类无法加载,直接跳过此类
|
// 由于依赖库导致的类无法加载,直接跳过此类
|
||||||
} catch (UnsupportedClassVersionError e) {
|
} catch (UnsupportedClassVersionError e) {
|
||||||
@ -280,23 +308,22 @@ public class ClassScaner implements Serializable{
|
|||||||
/**
|
/**
|
||||||
* 通过过滤器,是否满足接受此类的条件
|
* 通过过滤器,是否满足接受此类的条件
|
||||||
*
|
*
|
||||||
* @param clazz 类
|
* @param className 类名
|
||||||
* @return 是否接受
|
|
||||||
*/
|
*/
|
||||||
private void addIfAccept(String className) {
|
private void addIfAccept(String className) {
|
||||||
if(StrUtil.isBlank(className)) {
|
if (StrUtil.isBlank(className)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int classLen = className.length();
|
int classLen = className.length();
|
||||||
int packageLen = this.packageName.length();
|
int packageLen = this.packageName.length();
|
||||||
if(classLen == packageLen) {
|
if (classLen == packageLen) {
|
||||||
//类名和包名长度一致,用户可能传入的包名是类名
|
//类名和包名长度一致,用户可能传入的包名是类名
|
||||||
if(className.equals(this.packageName)) {
|
if (className.equals(this.packageName)) {
|
||||||
addIfAccept(loadClass(className));
|
addIfAccept(loadClass(className));
|
||||||
}
|
}
|
||||||
} else if(classLen > packageLen){
|
} else if (classLen > packageLen) {
|
||||||
//检查类名是否以指定包名为前缀,包名后加.(避免类似于cn.hutool.A和cn.hutool.ATest这类类名引起的歧义)
|
//检查类名是否以指定包名为前缀,包名后加.(避免类似于cn.hutool.A和cn.hutool.ATest这类类名引起的歧义)
|
||||||
if(className.startsWith(this.packageNameWithDot)) {
|
if (className.startsWith(this.packageNameWithDot)) {
|
||||||
addIfAccept(loadClass(className));
|
addIfAccept(loadClass(className));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -306,7 +333,6 @@ public class ClassScaner implements Serializable{
|
|||||||
* 通过过滤器,是否满足接受此类的条件
|
* 通过过滤器,是否满足接受此类的条件
|
||||||
*
|
*
|
||||||
* @param clazz 类
|
* @param clazz 类
|
||||||
* @return 是否接受
|
|
||||||
*/
|
*/
|
||||||
private void addIfAccept(Class<?> clazz) {
|
private void addIfAccept(Class<?> clazz) {
|
||||||
if (null != clazz) {
|
if (null != clazz) {
|
||||||
|
@ -10,7 +10,7 @@ public class ClassScanerTest {
|
|||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void scanTest() {
|
public void scanTest() {
|
||||||
ClassScaner scaner = new ClassScaner("cn.hutool.core.util.StrUtil", null);
|
ClassScaner scaner = new ClassScaner("cn.hutool.core.util", null);
|
||||||
Set<Class<?>> set = scaner.scan();
|
Set<Class<?>> set = scaner.scan();
|
||||||
for (Class<?> clazz : set) {
|
for (Class<?> clazz : set) {
|
||||||
Console.log(clazz.getName());
|
Console.log(clazz.getName());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user