diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/ClassScanner.java b/hutool-core/src/main/java/cn/hutool/core/lang/ClassScanner.java index 3b65a5d6c..06bca8ec3 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/ClassScanner.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/ClassScanner.java @@ -66,6 +66,16 @@ public class ClassScanner implements Serializable { */ private final Set> classes = new HashSet<>(); + /** + * 忽略loadClass时的错误 + */ + private boolean ignoreLoadError = false; + + /** + * 获取加载错误的类名列表 + */ + private final Set classesOfLoadError = new HashSet<>(); + /** * 扫描指定包路径下所有包含指定注解的类,包括其他加载的jar或者类 * @@ -221,6 +231,19 @@ public class ClassScanner implements Serializable { return scan(false); } + /** + * 扫描 + * + * @param forceScanJavaClassPaths 是否强制扫描其他位于classpath关联jar中的类 + * @param ignoreLoadError 是否或略扫描时loadClass的异常 + * @return 类集合 + * + */ + public Set> scan(boolean forceScanJavaClassPaths,boolean ignoreLoadError){ + this.ignoreLoadError = ignoreLoadError; + return scan(forceScanJavaClassPaths); + } + /** * 扫描包路径下满足class过滤器条件的所有class文件 * @@ -229,6 +252,11 @@ public class ClassScanner implements Serializable { * @since 5.7.5 */ public Set> scan(boolean forceScanJavaClassPaths) { + + //多次扫描时,清理上次扫描历史 + this.classes.clear(); + this.classesOfLoadError.clear(); + for (URL url : ResourceUtil.getResourceIter(this.packagePath)) { switch (url.getProtocol()) { case "file": @@ -267,8 +295,20 @@ public class ClassScanner implements Serializable { this.classLoader = classLoader; } + /** + * 忽略加载错误扫描后,可以获得之前扫描时加载错误的类名字集合 + */ + public Set getClassesOfLoadError(){ + return Collections.unmodifiableSet(this.classesOfLoadError); + } + // --------------------------------------------------------------------------------------------------- Private method start + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } + /** * 扫描Java指定的ClassPath路径 */ @@ -341,7 +381,7 @@ public class ClassScanner implements Serializable { * @param className 类名 * @return 加载的类 */ - private Class loadClass(String className) { + protected Class loadClass(String className) { ClassLoader loader = this.classLoader; if (null == loader) { loader = ClassLoaderUtil.getClassLoader(); @@ -353,10 +393,16 @@ public class ClassScanner implements Serializable { clazz = Class.forName(className, this.initialize, loader); } catch (NoClassDefFoundError | ClassNotFoundException e) { // 由于依赖库导致的类无法加载,直接跳过此类 + classesOfLoadError.add(className); } catch (UnsupportedClassVersionError e) { // 版本导致的不兼容的类,跳过 - } catch (Exception e) { - throw new RuntimeException(e); + classesOfLoadError.add(className); + } catch (Throwable e){ + if(!this.ignoreLoadError) { + throw new RuntimeException(e); + }else{ + classesOfLoadError.add(className); + } } return clazz; } diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/ClassScanerTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/ClassScanerTest.java index 8974f0384..2c2d243df 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/ClassScanerTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/ClassScanerTest.java @@ -32,4 +32,14 @@ public class ClassScanerTest { final Set> classes = ClassScanner.scanAllPackageBySuper(null, Iterable.class); Console.log(classes.size()); } + + + @Test + @Ignore + public void scanAllPackageIgnoreLoadErrorTest(){ + ClassScanner classScanner = new ClassScanner(null, null); + final Set> classes = classScanner.scan(false,true); + Console.log(classes.size()); + Console.log(classScanner.getClassesOfLoadError()); + } }