问题现象
使用proguard后的jar中的@Service类无法被自动加载,未使用proguard的可以被自动加载。
***************************
Description:
Field dictService in com.xx.xx.xx.xx.service.XxService required a bean of type 'com.xx.xx.xx.dict.service.DictService' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
问题追踪
org.springframework.core.io.support.PathMatchingResourcePatternResolver#findPathMatchingResources
if (rootDirResources == null) {
rootDirResources = this.getResources(rootDirPath);
if (this.useCaches == null || this.useCaches) {
this.rootDirCache.put(rootDirPath, rootDirResources);
}
}
org.springframework.core.io.support.PathMatchingResourcePatternResolver#doFindAllClassPathResources
protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {
Set<Resource> result = new LinkedHashSet(16);
ClassLoader cl = this.getClassLoader();
Enumeration<URL> resourceUrls = cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path);
while(resourceUrls.hasMoreElements()) {
URL url = (URL)resourceUrls.nextElement();
result.add(this.convertClassLoaderURL(url));
}
if (!StringUtils.hasLength(path)) {
this.addAllClassLoaderJarRoots(cl, result);
}
return result;
}
此处 cl.getResources(path) 无法读取到对应的目录的jar
编写测试类
为了方便调试,编写测试类,读取classloader中包含对应包且可以读取的jar
package com.xx.xx.xx.classloader;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
/**
* @author pp_lan
* @since 2026-03-09
*/
public class ProguardTest {
public static void main(String[] args) {
String path = "com/xx/xx/";
ClassLoader cl = ProguardTest.class.getClassLoader();
try {
Enumeration<URL> urls = cl.getResources(path);
if (!urls.hasMoreElements()) {
System.out.println("未找到任何资源。");
// 打印该类加载器能看到的 URL 列表(仅限 URLClassLoader)
if (cl instanceof java.net.URLClassLoader) {
java.net.URLClassLoader ucl = (java.net.URLClassLoader) cl;
for (java.net.URL url : ucl.getURLs()) {
System.out.println("Classpath 条目: " + url.getFile());
}
}
} else {
while (urls.hasMoreElements()) {
System.out.println("找到资源: " + urls.nextElement().toString());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
分析
比较混淆之前的jar和之后的jar,问题最大原因:
1. class存在,反编译工具打开后能看到对应的类及路径,但是目录条目本身不存在
修改
需要添加目录保留
# 保留目录条目(确保类加载器能识别目录资源)
-keepdirectories
验证
测试类验证通过
找到资源: file:/D:/workspace/xx/xx/retrieve/target/test-classes/com/xx/xx/
找到资源: file:/D:/workspace/xx/xx/retrieve/target/classes/com/xx/xx/
找到资源: jar:file:/D:/repository/com/xx/xx/xx-common/1.0.1-SNAPSHOT/xx-common-1.0.1-20260309.022850-2.jar!/com/xx/xx/
找到资源: jar:file:/D:/repository/com/xx/xx/xx-base/1.0.0-SNAPSHOT/xx-base-1.0.0-SNAPSHOT.jar!/com/xx/xx/
项目启动验证通过
启动成功

被折叠的 条评论
为什么被折叠?



