读取jar包中指定包名下的class

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ClassUtils;
import org.springframework.util.PathMatcher;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipException;

@Component
public class CustomResource implements ApplicationContextAware {
private ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}

@PostConstruct
public void init() throws IOException, ClassNotFoundException {
ClassLoader classLoader = applicationContext.getClassLoader();
String backageName = "com.x.x.x.";
Enumeration<URL> resources = classLoader.getResources(ClassUtils.convertClassNameToResourcePath(backageName));
ParseJar parseJar = new ParseJar();
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
if (ResourceUtils.isJarURL(url)) {
Set<Resource> classSet = parseJar.doFindPathMatchingJarResources(new UrlResource(url), url, "**/*.class");
for (Resource resource : classSet) {
System.out.println(resource.getFilename());
// Object o = BeanUtils.instantiateClass(ClassUtils.forName("", ContextLoader.class.getClassLoader()));
}
} else {
Set<Resource> classSet = parseJar.doFindPathMatchingFileResources(new UrlResource(url), "**/*.class");
for (Resource resource : classSet) {
System.out.println(resource.getFilename());
}
}
}
}

public class ParseJar {

protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource, String subPattern)
throws IOException {

File rootDir;
try {
rootDir = rootDirResource.getFile().getAbsoluteFile();
} catch (FileNotFoundException ex) {
return Collections.emptySet();
} catch (Exception ex) {
return Collections.emptySet();
}
return doFindMatchingFileSystemResources(rootDir, subPattern);
}

protected Set<Resource> doFindMatchingFileSystemResources(File rootDir, String subPattern) throws IOException {
Set<File> matchingFiles = retrieveMatchingFiles(rootDir, subPattern);
Set<Resource> result = new LinkedHashSet<>(matchingFiles.size());
for (File file : matchingFiles) {
result.add(new FileSystemResource(file));
}
return result;
}

protected Set<File> retrieveMatchingFiles(File rootDir, String pattern) throws IOException {
if (!rootDir.exists()) {
return Collections.emptySet();
}
if (!rootDir.isDirectory()) {
return Collections.emptySet();
}
if (!rootDir.canRead()) {
return Collections.emptySet();
}
String fullPattern = StringUtils.replace(rootDir.getAbsolutePath(), File.separator, "/");
if (!pattern.startsWith("/")) {
fullPattern += "/";
}
fullPattern = fullPattern + StringUtils.replace(pattern, File.separator, "/");
Set<File> result = new LinkedHashSet<>(8);
doRetrieveMatchingFiles(fullPattern, rootDir, result);
return result;
}

protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set<File> result) throws IOException {
for (File content : listDirectory(dir)) {
String currPath = StringUtils.replace(content.getAbsolutePath(), File.separator, "/");
if (content.isDirectory() && getPathMatcher().matchStart(fullPattern, currPath + "/")) {
if (!content.canRead()) {
} else {
doRetrieveMatchingFiles(fullPattern, content, result);
}
}
if (getPathMatcher().match(fullPattern, currPath)) {
result.add(content);
}
}
}

protected File[] listDirectory(File dir) {
File[] files = dir.listFiles();
if (files == null) {
return new File[0];
}
Arrays.sort(files, Comparator.comparing(File::getName));
return files;
}

protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource, URL rootDirURL, String subPattern)
throws IOException {

URLConnection con = rootDirURL.openConnection();
JarFile jarFile;
String jarFileUrl;
String rootEntryPath;
boolean closeJarFile;

if (con instanceof JarURLConnection) {
// Should usually be the case for traditional JAR files.
JarURLConnection jarCon = (JarURLConnection) con;
ResourceUtils.useCachesIfNecessary(jarCon);
jarFile = jarCon.getJarFile();
jarFileUrl = jarCon.getJarFileURL().toExternalForm();
JarEntry jarEntry = jarCon.getJarEntry();
rootEntryPath = (jarEntry != null ? jarEntry.getName() : "");
closeJarFile = !jarCon.getUseCaches();
} else {
// No JarURLConnection -> need to resort to URL file parsing.
// We'll assume URLs of the format "jar:path!/entry", with the protocol
// being arbitrary as long as following the entry format.
// We'll also handle paths with and without leading "file:" prefix.
String urlFile = rootDirURL.getFile();
try {
int separatorIndex = urlFile.indexOf(ResourceUtils.WAR_URL_SEPARATOR);
if (separatorIndex == -1) {
separatorIndex = urlFile.indexOf(ResourceUtils.JAR_URL_SEPARATOR);
}
if (separatorIndex != -1) {
jarFileUrl = urlFile.substring(0, separatorIndex);
rootEntryPath = urlFile.substring(separatorIndex + 2); // both separators are 2 chars
jarFile = getJarFile(jarFileUrl);
} else {
jarFile = new JarFile(urlFile);
jarFileUrl = urlFile;
rootEntryPath = "";
}
closeJarFile = true;
} catch (ZipException ex) {
return Collections.emptySet();
}
}

try {
if (!"".equals(rootEntryPath) && !rootEntryPath.endsWith("/")) {
// Root entry path must end with slash to allow for proper matching.
// The Sun JRE does not return a slash here, but BEA JRockit does.
rootEntryPath = rootEntryPath + "/";
}
Set<Resource> result = new LinkedHashSet<>(8);
for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements(); ) {
JarEntry entry = entries.nextElement();
String entryPath = entry.getName();
if (entryPath.startsWith(rootEntryPath)) {
String relativePath = entryPath.substring(rootEntryPath.length());
if (getPathMatcher().match(subPattern, relativePath)) {
result.add(rootDirResource.createRelative(relativePath));
}
}
}
return result;
} finally {
if (closeJarFile) {
jarFile.close();
}
}
}

private PathMatcher getPathMatcher() {
return new AntPathMatcher();
}

protected JarFile getJarFile(String jarFileUrl) throws IOException {
if (jarFileUrl.startsWith(ResourceUtils.FILE_URL_PREFIX)) {
try {
return new JarFile(ResourceUtils.toURI(jarFileUrl).getSchemeSpecificPart());
} catch (URISyntaxException ex) {
// Fallback for URLs that are not valid URIs (should hardly ever happen).
return new JarFile(jarFileUrl.substring(ResourceUtils.FILE_URL_PREFIX.length()));
}
} else {
return new JarFile(jarFileUrl);
}
}
}
}

原文地址:https://www.cnblogs.com/xufan/p/15397846.html