请教大家一个问题,如下:
我们知道,Spring中可以配置一个属性base-package,配置了这个属性以后,所有的在这个包或者子包下的类都将会被扫描,如果这些类配置了某些annotation,则将会被特别处理。
我的问题是spring是怎么拿到这些类的class的? 举个例子:类的层次结构如下:
com.test.action中有一个ListAction
com.test.service中有一个ListService
我配置了一个base-package为com.test那么我在程序中怎么知道有一个ListAction和ListService类?
我们知道,Spring中可以配置一个属性base-package,配置了这个属性以后,所有的在这个包或者子包下的类都将会被扫描,如果这些类配置了某些annotation,则将会被特别处理。
我的问题是spring是怎么拿到这些类的class的? 举个例子:类的层次结构如下:
com.test.action中有一个ListAction
com.test.service中有一个ListService
我配置了一个base-package为com.test那么我在程序中怎么知道有一个ListAction和ListService类?
pack ="/"+pack.replace(".", "/");
String packPath = System.getProperty("user.dir")+ "/src"+ pack;
这样可以先得到你的包所在目录的全路径,然后再写方法去遍历得到下面的所有类就可以啦
File dir = new File(getClass().getResource(pack).getFile());
File[] fs = dir.listFiles();
在WEB中也可以这样吗?
你的意思是 Spring 怎么做的么?可以告诉你,Spring 是采用 ASM 工具分析字节码,从中获取的。使用 ASM 的话可以不用加载类。
我没有想那么高级,我的目的只是想根据一个包名,例如com.test,那么我就能够在程序中扫描出这个包名下的所有类,楼上有一个人说的根据路径其实也可以,但是在WEB环境中可以吗?
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.jar.JarEntry;public class Main { public static void main(String[] args) throws IOException, URISyntaxException, ClassNotFoundException {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
String baseName = baseName(classloader);
Enumeration<URL> em = classloader.getResources("com/test");
while(em.hasMoreElements()) {
URL url = em.nextElement();
// jar 包中的
URLConnection connection = url.openConnection();
if("jar".equals(url.getProtocol()) && connection instanceof JarURLConnection) {
JarURLConnection jar = (JarURLConnection)connection;
JarEntry entry = jar.getJarEntry();
System.out.println(entry);
for(Enumeration<JarEntry> e = jar.getJarFile().entries(); e.hasMoreElements(); ) {
System.out.println(e.nextElement());
}
continue;
}
// 源代码中的
File file = new File(url.toURI());
File[] files = file.listFiles();
for(File f : files) {
scan(f, baseName, classloader);
}
}
} private static String baseName(ClassLoader classloader) throws URISyntaxException {
return new File(classloader.getResource("").toURI()).getAbsolutePath();
} private static void scan(File dir, String baseName, ClassLoader classloader) throws ClassNotFoundException {
if(dir.isDirectory()) {
File[] files = dir.listFiles();
for(File file : files) {
scan(file, baseName, classloader);
}
return;
}
scan2(dir, baseName, classloader);
} private static void scan2(File dir, String baseName, ClassLoader classloader) throws ClassNotFoundException {
String className = dir.getAbsolutePath().substring(baseName.length() + 1);
int dot = className.indexOf('.');
if(dot > -1) {
className = className.substring(0, dot);
}
if(className.indexOf('\\') > -1) {
className = className.replace('\\', '.');
}
if(className.indexOf('/') > -1) {
className = className.replace('/', '.');
}
Class<?> clazz = classloader.loadClass(className);
System.out.println(clazz.getName());
} protected static String determineRootDir(String location) {
int prefixEnd = location.indexOf(":") + 1;
int rootDirEnd = location.length();
while (rootDirEnd > prefixEnd && true) {
rootDirEnd = location.lastIndexOf('/', rootDirEnd - 2) + 1;
}
if (rootDirEnd == 0) {
rootDirEnd = prefixEnd;
}
return location.substring(0, rootDirEnd);
}
}