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:学而不思则罔,思而不学则殆。

原文地址:https://www.cnblogs.com/lingdurebing/p/ldrb-java.html

时间: 2024-08-29 23:50:56

java扫描某个包下的所有java类并加载的相关文章

Java语言Lang包下常用的工具类介绍_java - JAVA

文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 无论你在开发哪中 Java 应用程序,都免不了要写很多工具类/工具函数.你可知道,有很多现成的工具类可用,并且代码质量都很不错,不用你写,不用你调试,只要你发现. 在 Apache Jakarta Common 中, Lang 这个 Java 工具包是所有 Apache Jakarta Common 项目中被使用最广泛的,几乎你所知道的名气比较大的软件里面都有用到它,包括 Tomcat, Weblogic, Webs

Java误区: 静态代码块,会在类被加载时自动执行?

JAVA静态代码块会在类被加载时自动执行? 很多Java开发者的思想,被这个思想深深的轮奸了n遍,传播这个错误思想的博客,在网上一堆,越来越多的人被轮奸. 如:http://blog.csdn.net/leeyu35/article/details/7755304 那么我们程序来证明这句话是错误的: class MyClass1 { static {//静态块 System.out.println("static block "); } } public class Main { Cl

Java温故而知新(10)类的加载机制

类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指导开发者采取更有效的措施配合程序执行. 研究类加载机制的第二个目的是让程序能动态的控制类加载,比如热部署等,提高程序的灵活性和适应性. 1.类加载机制 我们来了解一下虚拟机如何加载Class文件. 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被直接使用的java类型,这就是虚拟机的类加载机制. 类的生命周期包括加载(Loading).验证(Verification).准

别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】

目录 1.什么是类的加载(类初始化) 2.类的生命周期 3.接口的加载过程 4.解开开篇的面试题 5.理解首次主动使用 6.类加载器 7.关于命名空间 8.JVM类加载机制 9.双亲委派模型 10.ClassLoader源码分析 11.自定义类加载器 12.加载类的三种方式 13.总结 14.特别注意 @ 前言 你是否真的理解java的类加载机制?点进文章的盆友不如先来做一道非常常见的面试题,如果你能做出来,可能你早已掌握并理解了java的类加载机制,若结果出乎你的意料,那就很有必要来了解了解j

深入java虚拟机(二)——类的生命周期(上)类的加载和连接

类加载器,顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中.一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件).类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例.每个这样的实例用来表示一个 Java 类.通过此实例的 newInstance()方法就可以创建出该类的一个对象.实际的情况可能

【转】Predicate和Consumer接口– Java 8中java.util.function包下的接口

原文链接 http://ifeve.com/predicate-and-consumer-interface-in-java-util-function-package-in-java-8/ 原文链接 作者:   Mohamed Sanaulla  译者: 李璟([email protected]) 早先我写了一篇<函数式接口>,探讨了部分Java 8中函数式接口的用法.我也提及了Predicate接口属于java.util.function包, 在这篇文章中,我将展示如何应用Predicat

java 类的加载、连接和初始化

JVM和类 调用Java命令运行Java程序时,该命令将会启动一条Java虚拟机进程,不管该Java程序启动了多少条线程,创建了多少个变量,它们都处于该Java虚拟机进程里,共享该JVM进程的内存区.当系统出现以下几种情况时,JVM进程将被终止: 程序运行到最后正常结束: 程序运行到使用System.exit()或Runtime.getRuntime.exit()代码结束程序: 程序运行过程中遇到未捕获的异常或错误而结束: 程序所在的平台强制结束了JVM进程. 类的加载 当程序主动使用某个类时,

java类的加载与初始化总结

1.触发类加载的原因(主动调用与被动调用): 六种主动调用: 1).创建类的实例(new操作.反射.cloning.反序列化) 2).调用类的静态方法 3).使用或对类/接口的static属性赋值(不包括static final的与在编译期确定的常量表达式(包括常量.字符串常量)) 4).调用API中的反射方法,Class.forName()等. 5).子类被初始化 6).被设定为JVM启动时的启动类(含main方法的主类) 其它都为被动引用:被动引用不会触发类的初始化操作(只会加载.链接),如

java虚拟机学习(四)类的加载过程

类从虚拟机内存加载到从内存卸载,经历的生命周期是:加载,验证,准备,解析,初始化,使用,卸载这几个阶段, 其中验证,解析,初始化被称为 连接过程(Linking). (打算这块和类加载原理后再看class文件结构那篇) 除了解析和使用,其他的过程基本顺序就是这样, 解析可以是在初始化完成之后,这是为了运行时动态绑定. 在虚拟机规范中定义了5中情况(有且只有)必须对类进行初始化(之前进行过,加载,验证,准备): 1.碰到new,getstatic,putstatic,invokestatic这4条