说明

spring 的功能非常强大,如何通过 spring 扫描指定包呢?

比如我们想获取指定包下的所有枚举。

实现

  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package com.github.houbb.spring.tool.utils; import com.github.houbb.heaven.util.lang.StringUtil; import com.github.houbb.spring.tool.exception.SpringToolException; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.util.ClassUtils; import java.util.ArrayList; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; /** * spring 包工具类 * * @since 1.0.0 */ public class SpringPackageUtil { /** * 扫描 * @param basePackages 基础包信息 * @param resourcePattern 资源正则 */ public static List<String> scanClassName(String basePackages, String resourcePattern) { try { List<String> classNameList = new ArrayList<>(); if(StringUtil.isEmpty(basePackages) || StringUtil.isEmpty(resourcePattern)) { return classNameList; } final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); // 根据classname生成class对应的资源路径,需要扫描的包路径 //ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + String pattern = ClassUtils.convertClassNameToResourcePath(basePackages) + resourcePattern; // 获取classname的IO流资源 Resource[] resources = resourcePatternResolver.getResources(pattern); // MetadataReaderFactory接口 ,MetadataReader的工厂接口。允许缓存每个MetadataReader的元数据集 MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver); for (Resource resource : resources) { if (resource.isReadable()) { // 通过class资源(resource)生成MetadataReader MetadataReader metadataReader = readerFactory.getMetadataReader(resource); // 获取class名 String className = metadataReader.getClassMetadata().getClassName(); classNameList.add(className); } } return classNameList; } catch (Exception e) { throw new SpringToolException(e); } } /** * 扫描 * @param basePackages 基础包信息 * @param resourcePattern 资源正则 */ public static List<Class> scanClass(String basePackages, String resourcePattern) { List<String> nameList = scanClassName(basePackages, resourcePattern); return nameList.stream().map((Function<String, Class>) s -> { try { return Class.forName(s); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } }).collect(Collectors.toList()); } }

测试

测试路径

  [plaintext]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
PS D:\code\learn\spring-tool\src\test> └─com └─github └─houbb └─spring └─tool │ package-info.java │ ├─enums │ MyBoolEnum.java │ package-info.java │ └─utils SpringPackageUtilTest.java

使用

  [java]
1
2
3
List<String> nameList = SpringPackageUtil.scanClassName("com.github.houbb.spring.tool.enums", "/**/*Enum.class"); System.out.println(nameList);

直接扫描包下面对应的 Enum 类信息。

  [plaintext]
1
[com.github.houbb.spring.tool.enums.MyBoolEnum]

参考资料

https://github.com/dianping/cat/blob/master/lib/java/README.zh-CN.md

https://github.com/dianping/cat/blob/master/integration/log4j2/README.md