扫描Class文件的方法

标签: class 文件 方法 | 发表时间:2014-03-20 21:01 | 作者:m310851010
出处:http://www.iteye.com

看了别人的代码多了,总能够学习一些东西的,把自己学的东西都点滴都记录下来.

今天自己以前写的一个简单的工具包,用来扫描类,可以扫描jar文件和包里的文件,说明如下:


1.扫描是某子类的Class,可以是包及其子包下的Class包括jar文件里的Class
2.扫描类上含有某(可以是多个)注解的Class,可以是包及其子包下的Class包括jar文件里的Class

 

直接贴部分代码吧:

 

还有其他依赖的类,由于篇幅原因就不贴出来了,下面说说怎么使用吧

 

 

public class ResolverUtil<T> {
  /*
   * An instance of Log to use for logging in this class.
   */
  private static final Logger log = LoggerFactory.getLogger(ResolverUtil.class);

  /**
   * A simple interface that specifies how to test classes to determine if they
   * are to be included in the results produced by the ResolverUtil.
   */
  public static interface Test {
    /**
     * Will be called repeatedly with candidate classes. Must return True if a class
     * is to be included in the results, false otherwise.
     */
    boolean matches(Class<?> type);
  }

  /**
   * A Test that checks to see if each class is assignable to the provided class. Note
   * that this test will match the parent type itself if it is presented for matching.
   */
  public static class IsA implements Test {
    private Class<?> parent;

    /** Constructs an IsA test using the supplied Class as the parent class/interface. */
    public IsA(Class<?> parentType) {
      this.parent = parentType;
    }

    /** Returns true if type is assignable to the parent type supplied in the constructor. */
    public boolean matches(Class<?> type) {
      return type != null && parent.isAssignableFrom(type);
    }

    @Override
    public String toString() {
      return "is assignable to " + parent.getSimpleName();
    }
  }

  /**
   * A Test that checks to see if each class is annotated with a specific annotation. If it
   * is, then the test returns true, otherwise false.
   */
  public static class AnnotatedWith implements Test {
    private Class<? extends Annotation> annotation;

    /** Constructs an AnnotatedWith test for the specified annotation type. */
    public AnnotatedWith(Class<? extends Annotation> annotation) {
      this.annotation = annotation;
    }

    /** Returns true if the type is annotated with the class provided to the constructor. */
    public boolean matches(Class<?> type) {
      return type != null && type.isAnnotationPresent(annotation);
    }

    @Override
    public String toString() {
      return "annotated with @" + annotation.getSimpleName();
    }
  }

  /** The set of matches being accumulated. */
  private Set<Class<? extends T>> matches = new HashSet<Class<? extends T>>();

  /**
   * The ClassLoader to use when looking for classes. If null then the ClassLoader returned
   * by Thread.currentThread().getContextClassLoader() will be used.
   */
  private ClassLoader classloader;

  /**
   * Provides access to the classes discovered so far. If no calls have been made to
   * any of the {@code find()} methods, this set will be empty.
   *
   * @return the set of classes that have been discovered.
   */
  public Set<Class<? extends T>> getClasses() {
    return matches;
  }

  public ClassLoader getClassLoader() {
    return classloader == null ? Thread.currentThread().getContextClassLoader() : classloader;
  }

  public void setClassLoader(ClassLoader classloader) {
    this.classloader = classloader;
  }

  public ResolverUtil<T> findImplementations(Class<?> parent, String... packageNames) {
    if (packageNames == null)
      return this;

    Test test = new IsA(parent);
    for (String pkg : packageNames) {
      find(test, pkg);
    }

    return this;
  }


  public ResolverUtil<T> findAnnotated(Class<? extends Annotation> annotation, String... packageNames) {
    if (packageNames == null)
      return this;

    Test test = new AnnotatedWith(annotation);
    for (String pkg : packageNames) {
      find(test, pkg);
    }

    return this;
  }

  public ResolverUtil<T> find(Test test, String packageName) {
    String path = getPackagePath(packageName);

    try {
      List<String> children = VFS.getInstance().list(path);
      for (String child : children) {
        if (child.endsWith(".class"))
          addIfMatching(test, child);
      }
    } catch (IOException ioe) {
      log.error("Could not read package: " + packageName, ioe);
    }

    return this;
  }

 
  public ResolverUtil<T> find(String packageName, Test test) {
	  return find(test, packageName);
  }
  
  public ResolverUtil<T> find(String packageName, Test ...test) {
    String path = getPackagePath(packageName);

    try {
      List<String> children = VFS.getInstance().list(path);
      for (String child : children) {
        if (child.endsWith(".class"))
          addIfMatching(child, test);
      }
    } catch (IOException ioe) {
      log.error("Could not read package: " + packageName, ioe);
    }

    return this;
  }
  
 
  protected String getPackagePath(String packageName) {
    return packageName == null ? null : packageName.replace('.', '/');
  }

  @SuppressWarnings("unchecked")
  protected void addIfMatching(Test test, String fqn) {
    try {
      String externalName = fqn.substring(0, fqn.indexOf('.')).replace('/', '.');
      ClassLoader loader = getClassLoader();
      log.debug("Checking to see if class " + externalName + " matches criteria [" + test + "]");

      Class<?> type = loader.loadClass(externalName);
      if (test.matches(type)) {
        matches.add((Class<T>) type);
      }
    } catch (Throwable t) {
      log.warn("Could not examine class '" + fqn + "'" + " due to a " +
          t.getClass().getName() + " with message: " + t.getMessage());
    }
  }
  
  @SuppressWarnings("unchecked")
  protected void addIfMatching( String fqn, Test ...test) {
	  try {
		  String externalName = fqn.substring(0, fqn.indexOf('.')).replace('/', '.');
		  ClassLoader loader = getClassLoader();
		  log.debug("Checking to see if class " + externalName + " matches criteria [" + test + "]");
		  
		  Class<?> type = loader.loadClass(externalName);
		  boolean flag = false;
		  for (int i = 0; i < test.length; i++) {
			  if (test[i].matches(type)) {
				  flag = true;
				  break;
			  }
		  }
		  if(flag){
			  matches.add((Class<T>) type);
		  }
	  } catch (Throwable t) {
		  log.warn("Could not examine class '" + fqn + "'" + " due to a " +
				  t.getClass().getName() + " with message: " + t.getMessage());
	  }
  }
}

 

 

public static void main(String[] args) {
		Set<Class<? extends Class<?>>> typeSet = null;
		ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
		
		//1.扫描org下的类Class,包括jar包里的Class
		resolverUtil.find(new ResolverUtil.IsA(Object.class), "org.slf4j");
		typeSet = resolverUtil.getClasses();
		System.out.println(typeSet);
		
		//2.以单个个注解方式扫描Class
		resolverUtil.findAnnotated(javax.annotation.Resource.class, "org.mdc");
		typeSet = resolverUtil.getClasses();
		System.out.println(typeSet);
		
		//3.以多个注解方式扫描Class
		resolverUtil.find("org.mdc", new ResolverUtil.AnnotatedWith(javax.annotation.Resource.class), new ResolverUtil.AnnotatedWith(javax.xml.ws.WebFault.class));
		typeSet = resolverUtil.getClasses();
		System.out.println(typeSet);
		
		
	}

 



    本文附件下载:
  • util.rar (35.8 KB)


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [class 文件 方法] 推荐:

扫描Class文件的方法

- - Java - 编程语言 - ITeye博客
看了别人的代码多了,总能够学习一些东西的,把自己学的东西都点滴都记录下来.. 今天自己以前写的一个简单的工具包,用来扫描类,可以扫描jar文件和包里的文件,说明如下:. 1.扫描是某子类的Class,可以是包及其子包下的Class包括jar文件里的Class. 2.扫描类上含有某(可以是多个)注解的Class,可以是包及其子包下的Class包括jar文件里的Class.

Java的 class文件结构

- - Java - 编程语言 - ITeye博客
Java-class文件结构.        我们都知道我们现在写的源代码计算机是不认识的,我们需要根据指定的编译器进行编译-连接-执行,这样才是我们想要的结果,所以计算机只能认识0或者1 ,那么如何与操作系统或者机器指令无关的程序能执行,那么在操作系统以及机器指令之上的那就是虚拟机了,这样我们编写的代码不再是最终形成二进制本地指令代码,而是一种在操作系统和机器指令之上的虚拟机规定的文件格式.

Javascript定义类(class)的三种方法

- - 阮一峰的网络日志
将近20年前, Javascript诞生的时候,只是一种简单的网页脚本语言. 如果你忘了填写用户名,它就跳出一个警告. 如今,它变得几乎无所不能,从前端到 后端,有着各种 匪夷所思的用途. 程序员用它完成越来越庞大的项目. Javascript代码的复杂度也直线上升. 单个网页包含10000行Javascript代码,早就司空见惯.

分析一个Java Class文件

- - CSDN博客推荐文章
Java源码文件TestClass.java:. 展示这个Class文件的16进制内容:. 00 00 00 34 : 版本号是1.8.0;. 00 16: 说明常量池有21个常量,1-21, index留做他用;接下来就是分别这21个常量的描述:. 07/00 02 :CONSTANT_Class_info 常量,类名索引是该常量池的第2项;.

Spring如何扫描class和配置文件

- - 企业架构 - ITeye博客
       前几天由于公司项目架构调整,想将以前代码开发为主改成配置文件配置为主,即所有的外部服务调用由配置文件组织,因为必须高效,所以涉及包括调用顺序,并发调用等,但配置文件的缺陷是只能实现简单的业务逻辑,所以我们还用了jeval表达式Jar包.        废话不多说,由于服务配置文件是放在Maven项目下的一个子模块的classpath下,该子模块在eclipse下运行是以用文件系统路径来扫描到并解析的,但在线上环境,该子模块是会被打成Jar包,就是说线上环境是需要解析该子模块的Jar包才能取到配置文件的.

class 文件与dex文件区别 (dvm与jvm区别)及Android DVM介绍

- - CSDN博客推荐文章
区别一:dvm执行的是.dex格式文件  jvm执行的是.class文件   android程序编译完之后生产.class文件,然后,dex工具会把.class文件处理成.dex文件,然后把资源文件和.dex文件等打包成.apk文件. apk就是android package的意思. jvm执行的是.class文件.

Django class-based view 基础

- Ken - python.cn(jobs, news)
自从Django在1.3中新增了class-based view以来,还没有仔细研究它,开始感觉这个东西是否有点多余. 因为Django已经有了Generic veiws了啊, 可是仔细看过class-based veiw之后, 这种想法打消了, 因为你完全可以用类方法实现你所有的视图, 而代码阅读起来却更容易!.

Django class-based view 深入

- Ken - python.cn(jobs, news)
上一篇我们粗略介绍了Django中的class-based view基础知识, 本篇我们继续来看关于class-based view的高级应用.. 我们继续沿用上篇中的model:. 我们来看看如何对一个Book实例进行更新, 我们要做的只是在视图类中更新 :.     template_name = 'updatebook.html'  #这里是你的模板文件名.

标签?ID?还是CLASS?

- - 前端观察
想谈一下几个基本的HTML问题,都是围绕着应该怎样使用HTML. 多用有语义的标签,少用div和span,避免使用没有class的div和span. 设想一下HTML的世界最初只有div和span这两个标签,其实网页依然可以写得出来. 更多标签的出现,其实是为了替代利用率高但不好书写的 
 和  来的.

偏好的 JavaScript Class 實作『基本款』

- Alu - Fred&#39;s blog
最近有一些想法,便和伙伴在空閒時間寫一些 Prototype 的專案,既然是嘗試形態的專案開發,就不必考慮穩定性和熟悉度,也不用顧慮失敗的問題,可以盡情玩弄新的,或是過去不常使用的技術. 所以,這次使用了 nodejs + express + HTML5 來開發,大玩 JavaScript. JavaScript 雖然看起來像 Java,但畢竟它不是真的 Java,很多功能考量以易於使用為優先,所以並不嚴謹,一些功能也因此被拿掉.