`
changhongbao
  • 浏览: 116634 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

java读取指定package下的所有class

 
阅读更多

之前在看spring注解的时候,有看到再配置文件里面定义component scan package就能自动扫描对应包下面的class,然后根据注解生成相应的bean。自己对这个功能很好奇,就搜了下,找到了实现的关键代码,记录下。后续再对这段代码深入学习。

package com.bch.scanner;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * 类扫描器,扫描给定包及其子包中的所有类
 * @author abao
 *
 */
public class ClassScanner {

/**
 * 从包package中获取所有的Class
 * 
 * @param pack
 * @return
 */
public static Set<Class<?>> getClasses(String pack) {

  // 第一个class类的集合
  Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
  // 是否循环迭代
  boolean recursive = true;
  // 获取包的名字 并进行替换
  String packageName = pack;
  String packageDirName = packageName.replace('.', '/');
  // 定义一个枚举的集合 并进行循环来处理这个目录下的things
  Enumeration<URL> dirs;
  try {
    dirs = Thread.currentThread()
	.getContextClassLoader()
	.getResources(packageDirName);
    // 循环迭代下去
    while (dirs.hasMoreElements()) {
     // 获取下一个元素
      URL url = dirs.nextElement();
     // 得到协议的名称
      String protocol = url.getProtocol();
     // 如果是以文件的形式保存在服务器上
      if ("file".equals(protocol)) {
       System.err.println("file类型的扫描");
       // 获取包的物理路径
        String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
       // 以文件的方式扫描整个包下的文件 并添加到集合中
        findAndAddClassesInPackageByFile(packageName, 
					filePath, recursive, classes);
     } else if ("jar".equals(protocol)) {
       // 如果是jar包文件
        // 定义一个JarFile
       System.err.println("jar类型的扫描");
       JarFile jar;
       try {
         // 获取jar
         jar = ((JarURLConnection) url.openConnection()).getJarFile();
         // 从此jar包 得到一个枚举类
          Enumeration<JarEntry> entries = jar.entries();
         // 同样的进行循环迭代
          while (entries.hasMoreElements()) {
           // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
             JarEntry entry = entries.nextElement();
            String name = entry.getName();
            // 如果是以/开头的
             if (name.charAt(0) == '/') {
              // 获取后面的字符串
                name = name.substring(1);
            }
            // 如果前半部分和定义的包名相同
              if (name.startsWith(packageDirName)) {
            int idx = name.lastIndexOf('/');
            // 如果以"/"结尾 是一个包
              if (idx != -1) {
              // 获取包名 把"/"替换成"."
              packageName = name.substring(0, idx).replace('/', '.');
             }
             // 如果可以迭代下去 并且是一个包
               if ((idx != -1) || recursive) {
               // 如果是一个.class文件 而且不是目录
                 if (name.endsWith(".class")&& !entry.isDirectory()) {
                 // 去掉后面的".class" 获取真正的类名
                   String className = name.substring(
                              packageName.length() + 1, name.length() - 6);
                 try {
                   // 添加到classes
                   classes.add(Class.forName(packageName + '.'+ className));
                 } catch (ClassNotFoundException e) {
                   // log
                   // .error("添加用户自定义视图类错误 找不到此类的.class文件");
                   e.printStackTrace();
                 }
               }
             }
           }
         }
       } catch (IOException e) {
         // log.error("在扫描用户定义视图时从jar包获取文件出错");
         e.printStackTrace();
       }
     }
    }
  } catch (IOException e) {
    e.printStackTrace();
  }

return classes;
}
	
/**
 * 以文件的形式来获取包下的所有Class
 * 
 * @param packageName
 * @param packagePath
 * @param recursive
 * @param classes
*/
public static void findAndAddClassesInPackageByFile(String packageName,
	String packagePath, final boolean recursive, Set<Class<?>> classes) {
// 获取此包的目录 建立一个File
File dir = new File(packagePath);
// 如果不存在或者 也不是目录就直接返回
if (!dir.exists() || !dir.isDirectory()) {
  // log.warn("用户定义包名 " + packageName + " 下没有任何文件");
  return;
}
// 如果存在 就获取包下的所有文件 包括目录
File[] dirfiles = dir.listFiles(new FileFilter() {
  // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
  public boolean accept(File file) {
    return (recursive && file.isDirectory())|| 
					(file.getName().endsWith(".class"));
}
});
// 循环所有文件
for (File file : dirfiles) {
// 如果是目录 则继续扫描
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(packageName + "."
		+ file.getName(), file.getAbsolutePath(), recursive,
		classes);
} else {
// 如果是java类文件 去掉后面的.class 只留下类名
String className = file.getName().substring(0,
					file.getName().length() - 6);
try {
// 添加到集合中去
//classes.add(Class.forName(packageName + '.' + className));
//经过回复同学的提醒,这里用forName有一些不好,会触发static方法,
//没有使用classLoader的load干净
classes.add(Thread.currentThread()
		.getContextClassLoader()
		.loadClass(packageName + '.' + className));  
} catch (ClassNotFoundException e) {
// log.error("添加用户自定义视图类错误 找不到此类的.class文件");
e.printStackTrace();
}
}
}
}

}

 

 

自己直接拿过来用了,可以扫描package对应的子package,不过是对当前classLoad下的所有jar进行扫描的。

分享到:
评论

相关推荐

    根据接口类名称和jar文件读取class文件

    根据接口类名称和jar文件读取class文件 可以改造成根据package名读取class文件等等。。。 扩展性很强一读既懂

    Java:二进制方式读取文件

    package hustspy.encrypt; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class File...

    Java读取资源文件工具类--ReadConfigation(java源码)

    public class ReadConfigation{ /** * 属性文件全名 */ private static final String PFILE ="Config.properties"; /** * 对应于属性文件的文件对象变量 */ private File m_file = null; /** ...

    Java文件处理工具类--FileUtil

    import java.io.*; /** * FileUtil. Simple file operation class. * * @author BeanSoft * */ public class FileUtil { /** * The buffer. */ protected static byte buf[] = new byte[1024]; /**...

    Spire.Pdf.zip 读取PDF文件中的信息

    读取PDF文件中的信息 package com.zht; import java.io.File; import java.io.UnsupportedEncodingException; import java.sql.Connection; import java.sql.DriverManager; import java.sql....

    class转成java源码-compilib:在运行时和内存中将Java源代码编译为Class对象

    类转成java源码相容 一个小的实用程序库,用于在运行时将Java源代码编译为* .class对象。 主要针对编写单元测试: Set&lt; String &gt; sources = new HashSet&lt;&gt; (); sources . put( " package a.b; \n " + " public...

    读取Properties文件的java类

    package cn.cucsi.ccs; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; ...

    Java解析XML工具类--(java源码)

    * 获得某节点下的某个子节点(指定子节点名称,和某个属性的值) * 即获取parentElement下名字叫childName,并且属性attributeName的值为attributeValue的子结点 * @param parentElement 要获取子节点的...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    8.1.3 天上掉下个package 197 8.1.4 包带来了什么? 197 8.2 import语句:化繁为简 200 8.2.1 import语句 200 8.2.2 一网打尽包中所有类 201 8.2.3 import语句带来的小问题 202 8.2.4 默认引入的包 204 8.3 ...

    Java 2实用教程(第三版)实验指导与习题解答

    Java 2实用教程(第三版)实验指导与习题解答 清华大学出版社 (编著 耿祥义 张跃平) 实验模版代码 建议使用文档结构图 (选择Word菜单→视图→文档结构图) 上机实践1 初识Java 4 实验1 一个简单的应用程序 ...

    读取sd卡图片

    读取sd卡图片并且显示到出来 package cn.itcast.test; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import android.graphics.Bitmap; import android.graphics....

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    8.1.3 天上掉下个package 197 8.1.4 包带来了什么? 197 8.2 import语句:化繁为简 200 8.2.1 import语句 200 8.2.2 一网打尽包中所有类 201 8.2.3 import语句带来的小问题 202 8.2.4 默认引入的包 204 8.3 ...

    Java JDK 7学习笔记(国内第一本Java 7,前期版本累计销量5万册)

    2.2.2 使用package管理类 33 2.2.3 使用import偷懒 36 2.3 使用ide 38 2.3.1 ide项目管理基础 38 2.3.2 使用了哪个jre 43 2.3.3 类文档版本 45 2.4 重点复习 48 2.5 课后练习 49 chapter3 基础语法 ...

    javapoet:用于生成.java源文件的Java API

    JavaPoet JavaPoet是用于生成.java源文件的Java API。 在执行诸如批注处理或与元数据文件(例如,数据库模式,协议格式)交互之类的操作时,源文件的生成可能非常有用。 通过生成代码,您无需编写样板文件,同时还...

    java解析给定url

    public class HtmlParse { List&lt;String&gt; configList = new ArrayList(); private String savePath = "d:\\htmlParse.txt"; private String reg = "[\u4E00-\u9FA5]+"; Set&lt;String&gt; resultSet = new ...

    基于JAVA的搜索引擎 lucene-2.2.0

    如果指定的索引目录下已经存在一些索引文件,并且指定create的值为false,则执行向已存在的索引文件中追加索引,就可以看到索引目录下面的文件不会发生变化,程序执行会因为write.lock文件而抛出异常: Exception ...

    Excel POI读取封装(文件+示范代码)

    package org.excel.service; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Field; import java....

    +Flex+集成到+Java+EE+应用程序的最佳实践(完整源代码)

    为了能完成自动生成 RemoteObject 对象,我编写了一个 Java2ActionScript 的 Ant 任务来自动转换 FlexService 接口以及相关的所有 JavaBean。JavaInterface2RemoteObjectTask 完成一个 Java 接口对象到 RemoteObject...

    安卓java读取网页源码-Andorid-learning:Andorid-学习

    安卓java读取网页源码 Andorid-learning 目录: 0-0 0-1 1-1 1-2 1-3 1-4 0-0 隐藏顶部栏状态栏 在代码 oncreate: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate...

    java万能DAO

    所有业务逻辑类皆可调用该类 package com.parddu.dao; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; ...

Global site tag (gtag.js) - Google Analytics