• java扫描某个包下的所有java类并加载


      最近在学习java的反射和注解,实际情景中需要扫描某个包下的所有java类,然后使用类加载器加载类。

      基本思路,获得程序的路径扫描src下某个包内的子包和java类,实现也比较简单。

      运行环境:windows10+jdk1.8+eclipse

      直接贴代码

      

    package org.test.scanner;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    
    /*
     * date:2019-07-23
     * */
    public class PackageScanner {
        private List<Class<?>> classes;
        private String packagePath = null;
    
        /*
         * 无参构造方法,内部调用带参的构造方法。
         * 
         * @throw classNotFound
         * 
         */
        public PackageScanner() throws ClassNotFoundException {
            this("");
        }
    
        /*
         * 实现,调用fileScanner进行目录扫描和加载
         * 
         * @param String 传入需要扫描的包
         * 
         * @throw classNotFound
         */
        public PackageScanner(String basePackage) throws ClassNotFoundException {
            packagePath = System.getProperty("user.dir") + "\src\";
            String filePath = packagePath + basePackage.replace('.', '\');
            classes = new ArrayList<Class<?>>();
            fileScanner(new File(filePath));
        }
    
        private void fileScanner(File file) throws ClassNotFoundException {
            if (file.isFile() && file.getName().lastIndexOf(".java") == file.getName().length() - 5) {//5是".java"的长度
                String filePath = file.getAbsolutePath();
                String qualifiedName = filePath.substring(packagePath.length(), filePath.length() - 5).replace('\', '.');
                System.out.println(qualifiedName);
                classes.add(Class.forName(qualifiedName));
                return;
            } else if (file.isDirectory()) {
                for (File f : file.listFiles())
                    fileScanner(f);
            }
        }
    
        /*
         * 得到加载到的类对象的List,返回的是ArrayList
         */
        public List<Class<?>> getClasses() {
            return this.classes;
        }
    }

      

    这是一个简单的包扫描类,这里直接使用Class.forName()加载扫描到的类

    我们可以看一下forName实现

    public static Class<?> forName(String className) throws ClassNotFoundException {
    	return forName0(className, true, ClassLoader.getCallerClassLoader());
    	}
    

    发现调用了ClassLoader.getCallerClassLoader() 

    从名字上可以看出是得到调用类的类加载器,我们可以看一下它的实现

    static ClassLoader getCallerClassLoader() {
    		// NOTE use of more generic Reflection.getCallerClass()
    		Class caller = Reflection.getCallerClass(3);
    		// This can be null if the VM is requesting it
    		if (caller == null) {
    			return null;
    		}
    		return caller.getClassLoader0();
    	}

    关键一句: Reflection.getCallerClass(3)。

    一直往上传递,直到获取到它的调用类,然后得到调用类的类加载器


    其中 REflection.getCallerClass()的参数有:

    0 和小于0  -   返回 Reflection类 

    1  -   返回自己的类 

    2  -    返回调用者的类 
    3. 4. ....层层上传。

    最后的目的就是谁调用这个类,调用类的类加载器就负责加载这个类。只有当它的加载类为null时,即没有任何加载器可用时,才使用getClassLoader0()这个native方法,这是启动类加载器的实现方法,如果不是java lib目录里的库,该类是不会被加载的。

    通过学习java 的包扫描和类加载,我简单的了解了java类加载器的用法。

    能力有限,如有错误请告知一声。

    ps:学而不思则罔,思而不学则殆。

  • 相关阅读:
    进程和线程(一)
    树和二叉树(一)
    栈和队列
    《Learning to Coordinate with Coordination Graphs in Repeated Single-Stage Multi-Agent Decision Problems》- ICML2018
    简单Socket网络通信
    Spring Websocket实现简易在线聊天功能
    Spring实现WebSocket通信
    Spring中配置使用slf4j + log4j
    构建web应用之——文件上传
    构建web应用之——SpringMVC实现CRUD
  • 原文地址:https://www.cnblogs.com/lingdurebing/p/ldrb-java.html
Copyright © 2020-2023  润新知