最近在学习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类并加载的更多相关文章

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

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 无论你在开发哪中 Java 应用程序,都免不了要写很多工具类/工具函数.你可知道,有很多现成的工具类可用,并且代码质量都 ...

  2. Java的静态代码块是否会在类被加载时自动执行?

    JAVA静态代码块会在类被加载时自动执行? 一.先看Java静态方法,静态变量 http://www.cnblogs.com/winterfells/p/7906078.html 静态代码块 在类中, ...

  3. 深入了解java虚拟机(JVM) 第十一章 类的加载

    一.类加载机制概述 虚拟机把描述类的数据从class文件加载到内存并对数据进行效验,解析和初始化,最终形成可以被虚拟机直接使用的java类型,这就是虚拟机的类加载机制. 二.类加载的机制 类加载的过程 ...

  4. java中new一个对象的执行过程及类的加载顺序

    1,new一个对象时代码的执行顺序 (1)加载父类(以下序号相同,表明初始化是按代码从上到下的顺序来的) 1.为父类的静态属性分配空间并赋于初值 1.执行父类静态初始化块; (2)加载子类 2.为子类 ...

  5. Java程序设计19——类的加载和反射-Part-A

    1 本文概要 本章介绍Java类的加载.连接和初始化的深入知识,并重点介绍Java反射相关的内容.本章知识偏底层点,这些运行原理有助于我们更好的把我java程序的运行.而且Java类加载器除了根加载器 ...

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

    类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指导开发者采取更有效的措施配合程序执行. 研究类加载机制的第二个目的是让程序能动态的控制类加载,比如热部署等,提高程序的灵活性 ...

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

    目录 1.什么是类的加载(类初始化) 2.类的生命周期 3.接口的加载过程 4.解开开篇的面试题 5.理解首次主动使用 6.类加载器 7.关于命名空间 8.JVM类加载机制 9.双亲委派模型 10.C ...

  8. [Java]类的生命周期(上)类的加载和连接[转]

    本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 类加载器,顾名思义,类加载器(class loader)用来加载 Java 类到 Java ...

  9. Java反射1——扫描某个包下的所有类

    1.从包package中获取所有的Class /** * 从包package中获取所有的Class * * @param pack * @return */ public static Set< ...

随机推荐

  1. JAVA时间工具类用法

    1.获得N天前的TIMESTAMP Calendar cl = Calendar.getInstance(); cl.add(Calendar.DAY_OF_YEAR, -7); Date date ...

  2. C++ vector操作--往列表中添加或更新内容

    有个列表,往里面添加内容,如果对象已存在,只更新其属性,否则添加新一项. #include <iostream> #include <string> #include < ...

  3. elasticsearch.net一个查询问题

    .Query(q => q.Bool(b => b.Must(m => m.MultiMatch(t => t .Fields(f => f.Field(obj => ...

  4. Linux的s、t、i、a权限(转)

    原文链接:http://blog.chinaunix.net/uid-712656-id-2678715.html 文件权限除了r.w.x外还有s.t.i.a权限: s:文件属主和组设置SUID和GU ...

  5. sql(7)

    EXCEPT是指在第一个集合中存在,但是不存在于第二个集合中的数据. EXCEPT 子句/运算符用于将两个 SELECT 语句结合在一起,并返回第一个 SELECT 语句的结果中那些不存在于第二个 S ...

  6. jQuery实现的文字逐行向上间歇滚动效果示例

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  7. 廖雪峰Java16函数式编程-1Lambda表达式-1Lambda基础

    1. 函数式编程 Java有2类方法: 实例方法:通过实例调用 静态方法:通过类名调用 Java的方法相当于过程式语言的函数 函数式编程(Functional Programing): 把函数作为基本 ...

  8. day33 序列类型,绑定方法,类方法,静态方法,封装继承和多态

    Python之路,Day20 = 序列类型,绑定方法,类方法,静态方法,封装继承和多态 序列是指有序的队列,重点在"有序". 一.Python中序列的分类 Python中的序列主要 ...

  9. thinkphp Trace方法

    页面Trace只能用于有页面输出的情况,但是trace方法可以用在任何情况,而且trace方法可以用于AJAX等操作. Trace方法的格式: trace('变量','标签','级别','是否记录日志 ...

  10. flask中abort()函数的使用

    一.介绍 #从flask中导入abort from flask import abort abort()函数的作用 可以让开发者在检测到web访问错误时,立即将错误信息返回回去,返回的错误码必须是已知 ...