首页 文章

在ClassLoader中加载Spring Boot类

提问于
浏览
0

我需要读一个Spring Boot jar并加载ClassLoader上的所有clases .

我的问题,在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中的类

2 回答

  • 0

    我最后在一个临时目录中选择了解压缩de jar并使用以下条目创建一个URLClassloader:一个到根目录 . 一个到BOOT-INF / classes,一个用于BOOT-INT / lib中的每个jar

    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);
        }
    }
    
  • 0

    调查一下spring boot如何加载第三方(Liquibase)类,我会这样:

    鉴于您知道要加载的包名称

    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);
            }
        }
    

    也可以使用带有加载jar的类加载器:

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

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

相关问题