最近在学习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. Spring注解基础学习总结

    1.依赖注入注解: @Component:Bean注入到Spring容器组件(通用) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE):Bean作用域( ...

  2. 2018-8-10-VisualStduio-打断点调试和不打断点调试有什么区别

    title author date CreateTime categories VisualStduio 打断点调试和不打断点调试有什么区别 lindexi 2018-08-10 19:16:52 + ...

  3. Dede没见过的漏洞

    payload:plus/search.php?keyword=xxx&arrs1[]=99&arrs1[]=102&arrs1[]=103&arrs1[]=95&am ...

  4. 利用DNSQuery 进行DNS查询

    #include <WinSock2.h> #include <WinDNS.h> #pragma comment (lib, "Dnsapi.lib") ...

  5. Android开发 View的UI刷新Invalidate和postInvalidate

    Invalidate 正常刷新 /** * 使整个视图无效.如果视图可见, * {@link #onDraw(android.graphics.Canvas)} 调用此方法后将在后续的UI刷新里调用o ...

  6. apache 80 端口 反向代理 tomcat 8080端口

    最近有个jsp的项目要放到服务上,但服务器上已经有了XAMPP(apache + mysql + php), 已占用了80端口.但http默认是访问80端口的. 先把tomcat 环境搭建起来, 发现 ...

  7. Java 虚拟机 - GC机制

    GC机制的一些总结 https://blog.csdn.net/super_qing_/article/details/85263991 https://blog.csdn.net/yhyr_ycy/ ...

  8. scala中的闭包简单使用

    object Closure { /** * scala中的闭包 * 函数在变量不处于其有效作用域内,还能够对变量进行访问 * * @param args */ def main(args: Arra ...

  9. Remember, every day is a miracle.

    Remember, every day is a miracle.请记住,每一天都是一个奇迹.

  10. Windows start

    启动一个单独的窗口以运行指定的程序或命令. START ["title"] [/D path] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]   ...