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

Posted lingdurebing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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:学而不思则罔,思而不学则殆。

以上是关于java扫描某个包下的所有java类并加载的主要内容,如果未能解决你的问题,请参考以下文章

Java 包扫描器

使用java怎么扫描指定包下的类

使用java怎么扫描指定包下的类

java 获取包下的所有类,附完整源码和测试代码

java8--类加载机制与反射(java疯狂讲义3复习笔记)

Java 扫描某包下所有类的注解并获得注解值