手写web框架之开发一个类加载器

  1 ackage io.renren.common;
  2 
  3 import lombok.extern.slf4j.Slf4j;
  4 import org.apache.commons.lang3.StringUtils;
  5 
  6 import java.io.File;
  7 import java.io.FileFilter;
  8 import java.io.IOException;
  9 import java.net.JarURLConnection;
 10 import java.net.URL;
 11 import java.util.Enumeration;
 12 import java.util.HashSet;
 13 import java.util.Set;
 14 import java.util.jar.JarEntry;
 15 import java.util.jar.JarFile;
 16 
 17 @Slf4j
 18 public class ClassUtil {
 19 
 20     /**
 21      * 获取类加载器
 22      * 获取加载器类的实现比较简单,只需获取当前线程的ClassLoader
 23      */
 24     public static ClassLoader getClassLoader() {
 25         return Thread.currentThread().getContextClassLoader();
 26     }
 27 
 28     /**
 29      * **
 30      * 加载类
 31      * 加载类需要提供类名与是否初始化的标志,这里提到的初始化指是否执行类的静态代码块;
 32      * 为了提高加载类的性能,可以将loadClass方法的isInitialized参数设置false
 33      */
 34     public static Class<?> loadClass(String className, boolean isInitialized) {
 35         Class<?> cls = null;
 36         try {
 37            cls= Class.forName(className, isInitialized, getClassLoader());
 38         } catch (ClassNotFoundException e) {
 39             log.error("load class failure.", e);
 40             throw new RuntimeException(e);
 41         }
 42         return cls;
 43     }
 44 
 45     /**
 46      * 获取指定包名下的所有类
 47      */
 48     public static Set<Class<?>> getClassSet(String packageName) {
 49         Set<Class<?>> classSet = new HashSet<Class<?>>();
 50         try {
 51             Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".", "/"));
 52             while (urls.hasMoreElements()) {
 53                 URL url = urls.nextElement();
 54                 if (url != null) {
 55                     String protocol = url.getProtocol();
 56                     if ("file".equals(protocol)) {
 57                         String packagePath = url.getPath().replace("%20", "");
 58                         addClass(classSet, packagePath, packageName);
 59                     } else if ("jar".equals(protocol)) {
 60                         JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
 61                         if (jarURLConnection != null) {
 62                             JarFile jarFile = jarURLConnection.getJarFile();
 63                             if (jarFile != null) {
 64                                 Enumeration<JarEntry> jarEntries = jarFile.entries();
 65                                 while (jarEntries.hasMoreElements()) {
 66                                     JarEntry jarEntry = jarEntries.nextElement();
 67                                     String jarEntryName = jarEntry.getName();
 68                                     if (jarEntryName.endsWith(".class")) {
 69                                         String className = jarEntryName.substring(0, jarEntryName.lastIndexOf("."))
 70                                                 .replaceAll("/", ".");
 71                                         doAddClass(classSet, className);
 72                                     }
 73                                 }
 74                             }
 75                         }
 76                     }
 77                 }
 78             }
 79         } catch (IOException e) {
 80             log.error("get class set failure.", e);
 81             throw new RuntimeException(e);
 82         }
 83         return classSet;
 84     }
 85 
 86     private static void addClass(Set<Class<?>> classSet, String packagePath, String packageName) {
 87         File[] files = new File(packagePath).listFiles(new FileFilter() {
 88             public boolean accept(File file) {
 89                 return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
 90             }
 91         });
 92         for (File file : files) {
 93             String fileName = file.getName();
 94             if (file.isFile()) {
 95                 String className = fileName.substring(0, fileName.lastIndexOf("."));
 96                 if (StringUtils.isNotEmpty(packageName)) {
 97                     className = packageName + "." + className;
 98                 }
 99                 doAddClass(classSet, className);
100             } else {
101                 String subPackagePath = fileName;
102                 if (StringUtils.isNotEmpty(packageName)) {
103                     subPackagePath = packagePath + "/" + subPackagePath;
104                 }
105                 String subPackageName = fileName;
106                 if (StringUtils.isNotEmpty(packageName)) {
107                     subPackageName = packageName + "." + subPackageName;
108                 }
109                 addClass(classSet, subPackagePath, subPackageName);
110             }
111         }
112     }
113 
114     private static void doAddClass(Set<Class<?>> classSet, String className) {
115         Class<?> cls = loadClass(className, true);
116         classSet.add(cls);
117     }

实现扫描包路径下类的功能

猜你喜欢

转载自www.cnblogs.com/duan2/p/11748058.html
今日推荐