Java的类加载机制
Java的代码都是运行在JVM虚拟机中的,使用类加载机制来完成代码的运行,具体内容还不是很了解,但是类加载机制总需要有一个线程来操作,Web框架中的类加载工具就是获取到这个线程,并把框架里的类加载进去.
类加载工具流程
- 新建一个HashSet存放Class
- 通过File文件目录/jar包/“.class”文件三种方式遍历取出Class
- 获取到类加载线程进行加载
Example
package org.smart4j.framework.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smart4j.framework.util.tool.StringUtil;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public final class ClassUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class);
public static Set<Class<?>> getClassSet (String packageName) {
//init a Classset
Set<Class<?>> classSet = new HashSet<Class<?>>();
//loop for find Class
try {
Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".","/"));
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null) {
String protocol = url.getProtocol();
if (protocol.equals("file")) {
String packagePath = url.getPath().replaceAll("%20"," ");
addClass(classSet, packagePath,packageName);
}else if (protocol.equals("jar")) {
JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection();
if (jarURLConnection != null) {
JarFile jarFile = jarURLConnection.getJarFile();
if (jarFile != null) {
Enumeration<JarEntry> jarEnties = jarFile.entries();
while (jarEnties.hasMoreElements()) {
JarEntry jarEntry = jarEnties.nextElement();
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
return classSet;
}
private static void doAddClass(Set<Class<?>> classSet, String className) {
Class<?> cls = loadClass(className, false);
classSet.add(cls);
}
private static void addClass(Set<Class<?>> classSet, String packagePath, final String packageName) {
final File[] files = new File(packagePath).listFiles(new FileFilter() {
public boolean accept(File pathname) {
return (pathname.isFile() && pathname.getName().endsWith(".class"))|| pathname.isDirectory();
}
});
for (File file: files) {
//Get File name
String fileName = file.getName();
//
if (file.isFile()) {
String className = fileName.substring(0,fileName.lastIndexOf("."));
if (StringUtil.isNotEmpty(packageName)) {
className = packageName+"."+className;
}
doAddClass(classSet, className);
}else {
String subPackagePath = fileName;
if (StringUtil.isNotEmpty(packagePath)) {
subPackagePath = packagePath + "/" + subPackagePath;
}
String subPackageName = fileName;
if (StringUtil.isNotEmpty(packageName)) {
subPackageName = packageName + "." +subPackageName;
}
addClass(classSet, subPackagePath, subPackageName);
}
}
}
public static Class<?> loadClass(String className, boolean isInitialized) {
Class<?> cls;
try {
cls = Class.forName(className,isInitialized, getClassLoader());
} catch (ClassNotFoundException e) {
LOGGER.error("load class failure",e);
throw new RuntimeException(e);
}
return cls;
}
public static ClassLoader getClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
}