使用Proguard混淆后spring中的bean无法自动加载分析

Python3.8

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

问题现象

使用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/

项目启动验证通过

启动成功

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值