类扫描

 主要用到的东西:
     1、资源获取:

 ClassLoader loader = getClass().getClassLoader();
 loader.getResources(name);

        例如:

 loader.getResources("com/test");

         可能会找到多个包含"com/test"的资源路径

 file:/D:/****/bin/com/test                 -- file:这个是协议,file代表文件,jar代表架包
 jar:file:/D:/****/lib/***.jar!/com/test    -- 符号"!/"后面代表着jar内部的路径
 jar:file:/D:/****/lib/***2.jar!/com/test

        测试的时候发现,极个别 jar包,可以正常使用 jar包中的类,但是通过 ClassLoader.getResources()方法,获取不到 jar资源,但是把 jar包重新打包就又可以获取到了,这个问题待研究。

        相关的东西备忘下:

            Class和 ClassLoader类里都获取单个资源的方法 getResource()。Class是从当前路径找,从根目录找需要加 "/",ClassLoader直接从根目录找。

            Class里面没有获取全部资源的 getResources() 方法。

            Class里面有一个比较实用的 getResourceAsStream(),直接可以获取流。

     2、Jar包处理:

 /* url可以指向jar包中的某个资源 */
 JarURLConnection conn = (JarURLConnection) url.openConnection();
 /* 获取jar包对象 */
 JarFile jar = conn.getJarFile();
 /* 获取jar包中的所有资源 */
 Enumeration<JarEntry> entrys = jar.entries();

     3、文件夹处理:递归遍历文件夹
     4、获取 Class对象

 ClassLoader loader = getClass().getClassLoader();
 loader.loadClass(className);

        相关的东西备忘下:

             ClassLoader.loadClass()和 Class.forName()是有区别的。

             JVM的类加载分三部:loading(加载文件)、linking(加载到JVM)、initializing(类初始化)。

             loadClass()只是到 loading步骤,而 forName()可以到 initializing(默认) 或者 linking(参数控制)步骤。


 包扫描全部代码:

 import java.io.File;
 import java.io.IOException;
 import java.net.JarURLConnection;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.Enumeration;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;

 /**
  * 类扫描器
  */
 public class Scanner {

     /** 类加载器 */
     private static ClassLoader loader = Scanner.class.getClassLoader();

     /**
      * 扫描类
      * 
      * @param pack 包名
      * @return 类
      */
     public static List<Class<?>> scan(String pack) {

         pack = pack.replace('.', '/');

         Enumeration<URL> urls;
         try {
             /* 获取资源列表 */
             urls = loader.getResources(pack);

         } catch (IOException e) {
             throw new RuntimeException(e);
         }

         List<Class<?>> classList = new LinkedList<Class<?>>();
         /* 遍历 */
         while (urls.hasMoreElements()) {

             URL url = urls.nextElement();
             String protocol = url.getProtocol();
 
             if ("jar".equals(protocol)) {
                 /* 如果是jar包内的资源 */
                 classList.addAll(scanFromJar(url, pack));
             } else if ("file".equals(protocol)) {
                 /* 如果是文件资源 */
                 classList.addAll(scanFromDir(url, pack));
             }
         }

         return classList;
     }

     /**
      * 获取Jar包类资源
      * 
      * @param url 资源URL
      * @param pack 包名
      * @return 类
      */
     private static List<Class<?>> scanFromJar(URL url, String pack) {

         JarFile jar;
         try {
             /* 获取Jar包文件对象 */
             JarURLConnection conn = (JarURLConnection) url.openConnection();
             jar = conn.getJarFile();

         } catch (IOException e) {
             return new LinkedList<Class<?>>();
         }

         return scanFromJar(jar, pack);
     }

     /**
      * 获取Jar包类资源
      * 
      * @param jar JarFile对象
      * @param pack 包名
      * @return 类
      */
     public static List<Class<?>> scanFromJar(JarFile jar, String pack) {

         List<Class<?>> classList = new LinkedList<Class<?>>();

         /* 这里取到的是Jar包里所有的文件,需要过滤 */
         Enumeration<JarEntry> entrys = jar.entries();
         /* 遍历 */
         while (entrys.hasMoreElements()) {

             String name = entrys.nextElement().getName();

             if (name.startsWith(pack) && name.endsWith(".class")) {

                 String className = name.substring(0, name.length() - 6);
                 className = className.replace('/', '.');

                 try {
                     /* 加载类对象 */
                     Class<?> c = loader.loadClass(className);
                     classList.add(c);
 
                 } catch (ClassNotFoundException e) {
                 }
             }
         }
         return classList;
     }

     /**
      * 获取文件夹类资源
      * 
      * @param url 资源URL
      * @param pack 包名
      * @return 类
      */
     private static List<Class<?>> scanFromDir(URL url, String pack) {

         File dir;
         try {
             /* 转行为file对象 */
             dir = new File(url.toURI());
         } catch (URISyntaxException e) {
             return new LinkedList<Class<?>>();
         }

         return scanFromDir(dir, pack);
     }

     /**
      * 获取文件夹类资源
      * 
      * @param dir 文件夹对象
      * @param pack 包名
      * @return 类
      */
     public static List<Class<?>> scanFromDir(File dir, String pack) {

         List<Class<?>> classList = new LinkedList<Class<?>>();

         File[] files = dir.listFiles();
         for (File file : files) {
             if (file.isDirectory()) {
                 /* 递归 */
                 classList.addAll(scanFromDir(file, pack + '/' + file.getName()));

             } else if (file.getName().endsWith(".class")) {

                 String fileName = file.getName();
                 String className = pack + '/' + fileName.substring(0, fileName.length() - 6);
                 className = className.replace('/', '.');

                 try {
                     /* 加载类对象 */
                     Class<?> c = loader.loadClass(className);
                     classList.add(c);

                 } catch (ClassNotFoundException e) {
                 }
             }
         }
         return classList;
     }
 }
 /* 调用方式 */
 List<Class<?>> classList = Scanner.scan("com.test");

转载于:https://my.oschina.net/loongzcx/blog/372273

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值