在 ClassLoader 中加载 Spring Boot 类

Load Spring Boot Classes in ClassLoader

我需要读取 Spring 引导 jar 并将所有类加载到 ClassLoader。

我的问题,spring 启动 类 位于“/BOOT-INF/classes”目录而不是根目录。

有人知道我如何在我的 ClassLoader 中加载这个 类 吗?

我尝试这样做:

private URLClassLoader getURLClassLoaderFromJar(Path jarPath) throws MalformedURLException {
        return URLClassLoader
                .newInstance(new URL[] { new URL("jar:file:" + jarPath.toAbsolutePath().toString() + "!/") });
}

这会加载 jar,但不会在 /BOOT-INF/classes

中加载 类

稍微调查一下 spring 引导如何加载第三方 (Liquibase) classes,我会这样:

假设您知道要加载的包名称

Resource[] scan(ClassLoader loader, String packageName) throws IOException {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(
                loader);
        String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                + ClassUtils.convertClassNameToResourcePath(packageName) + "/**/*.class";
        Resource[] resources = resolver.getResources(pattern);
        return resources;
    }


void findAllClasses(String packageName, ClassLoader loader) throws ClassNotFoundException {
        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(
                loader);
        try {
            Resource[] resources = scan(loader, packageName);
            for (Resource resource : resources) {
                MetadataReader reader = metadataReaderFactory.getMetadataReader(resource);
                ClassUtils.forName(reader.getClassMetadata().getClassName(), loader)
            }
        } catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }

也可以使用您的 class 加载器加载 jar:

findAllClasses("com.package", getURLClassLoaderFromJar(pathToJar));

此变体可以安全地与 Spring 启动打包一起使用 可执行 JAR

我最终选择在一个临时目录上解压 de jar 并使用以下条目创建一个 URLClassloader: 一到根目录。 一到 BOOT-INF/classes BOOT-INT/lib

中的每个罐子一个
Path warDirectory = decompressWar(absolutePathFile);

File rootDir = new File(warDirectory.toAbsolutePath().toString());
File springBootDir = new File(warDirectory.toAbsolutePath().toString() + "/BOOT-INF/classes/");

List<URL> listaURL = new ArrayList<URL>();
listaURL.add(rootDir.toURI().toURL());
listaURL.add(springBootDir.toURI().toURL());

//This scan the BOOT-INF/lib folder and return a List<URL> with all the libraries.
listaURL.addAll(getURLfromSpringBootJar(warDirectory));


URL[] urls = new URL[listaURL.size()];
urls = listaURL.toArray(urls);
cl = new URLClassLoader(urls);

//This explore the JAR and load all the .class fulies to get the className.
resultClassesBean = loadJars(Collections.singletonList(pathJarFile), cl);

if(resultClassesBean != null && resultClassesBean.getListResultClasses() != null && !resultClassesBean.getListResultClasses().isEmpty()) {
    for(String clazz : resultClassesBean.getListResultClasses()) {
        cl.loadClass(clazz);
    }
}