对于给定指定包名获取所有的类
对于一个IOC框架来说,这个功能是最基本,但是对于初学者来说确实不好来完成。接下来我会先贴代码,然后根据代码分析。
/**
* 对于制定包名的加载类
* author:Lizhao
* Date:15/12/16
* version:1.0
*
* @param pacckageName
*
* @return
*/
public static Set<Class<?>> getClassSet(String pacckageName) {
Set<Class<?>> classSet = new HashSet<Class<?>>();
try {
// 得到制定包名下面的资源
Enumeration<URL> urls = getClassloader().getResources(pacckageName.replace(".", "/"));
while (urls.hasMoreElements()) {
// url 格式file:/D:/eclipse/workspace/demo/WebContent/WEB-INF/classes/config/aaa.txt
URL url = urls.nextElement();
if (url != null) {
String protocol = url.getProtocol();// 返回协议 是file 还是 jar
if (protocol.equals("file")) {
// 20%是URL的空格,将其代替,SUN公司也说明了这是一个BUG
String packagePath = url.getPath().replaceAll("%20", " ");
addClass(classSet, packagePath, pacckageName);
}
else if(protocol.equals("jar")){
//如果是Jar则建立连接
JarURLConnection jarURLConnection= (JarURLConnection) url.openConnection();
if(jarURLConnection!=null){
//得到Jarfile对象
JarFile jarFile=jarURLConnection.getJarFile();
//如果jarFile不为空
if(jarFile!=null){
//得到jarw文件内的实体
Enumeration<JarEntry> jarEntries=jarFile.entries();
while (jarEntries.hasMoreElements()){//遍历实体
JarEntry jarEntry=jarEntries.nextElement();
//得到jar实体的名字 例如javax/crypto/SecretKey.class
String jarEntryName=jarEntry.getName();
if(jarEntryName.endsWith(".class")){
String className=jarEntryName.substring(0,jarEntryName.lastIndexOf(".")).replaceAll("/",".");
doAddClass(classSet,className);
}
}
}
}
}
}
}
} catch (IOException e) {
LOGGER.error("get class set failure",e);
throw new RuntimeException(e);
}
return classSet;
}
/**
*
* author:Lizhao
* Date:15/12/16
* version:1.0
*
* @param classSet
* @param packagePath
* @param pacckageName
*/
private static void addClass(Set<Class<?>> classSet, String packagePath, String pacckageName) {
File[] files = new File(packagePath).listFiles(new FileFilter() {
// 目录过滤器,过滤class文件和文件夹
@Override
public boolean accept(File file) {
return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
}
});
for (File file : files) {
String fileName = file.getName();
if (file.isFile()) {
// 截取.class之前的部分
String className = fileName.substring(0, fileName.lastIndexOf("."));
if (StringUtil.isNotEmpty(pacckageName)) {
// 包名加类名
className = pacckageName + "." + className;
}
doAddClass(classSet, className);
} else {
// 如果是文件夹,就把路径和包名都相加,继续迭代
String subPackagePath = fileName;
if (StringUtil.isNotEmpty(packagePath)) {
subPackagePath = packagePath + "/" + subPackagePath;
}
String subPackageName = fileName;
if (StringUtil.isNotEmpty(pacckageName)) {
subPackageName = pacckageName + "." + subPackageName;
}
//执行添加类
addClass(classSet, subPackagePath, subPackageName);
}
}
}
/**
* 添加类加载
* author:Lizhao
* Date:15/12/16
* version:1.0
*
* @param classSet
* @param className
*/
private static void doAddClass(Set<Class<?>> classSet, String className) {
Class<?> cls = loadClass(className, false);
classSet.add(cls);
}
对于上面一些部分有详细地说明,接下来对代码逐一分析。
1.Set