如何搜索带注释类的整个类路径?
我正在创建一个库,希望允许用户注释他们的类,因此当Web应用程序启动时,我需要扫描整个类路径以查找某些注释。
我正在考虑类似于Java EE 5 Web服务或EJB的新功能。你用@WebService或@EJB注释你的类,系统会在加载时找到这些类,这样就可以远程访问它们。
如何搜索带注释类的整个类路径?
我正在创建一个库,希望允许用户注释他们的类,因此当Web应用程序启动时,我需要扫描整个类路径以查找某些注释。
我正在考虑类似于Java EE 5 Web服务或EJB的新功能。你用@WebService或@EJB注释你的类,系统会在加载时找到这些类,这样就可以远程访问它们。
当前回答
反射似乎比Spring快得多。找到了解决这一差异的特性请求:http://www.opensaga.org/jira/browse/OS-738
这就是为什么在开发过程中使用reflection作为应用程序的启动时间是非常重要的。对于我的用例来说,Reflections似乎也很容易使用(找到一个接口的所有实现者)。
其他回答
You can find classes with any given annotation with ClassGraph, as well as searching for other criteria of interest, e.g. classes that implement a given interface. (Disclaimer, I am the author of ClassGraph.) ClassGraph can build an abstract representation of the entire class graph (all classes, annotations, methods, method parameters, and fields) in memory, for all classes on the classpath, or for classes in whitelisted packages, and you can query that class graph however you want. ClassGraph supports more classpath specification mechanisms and classloaders than any other scanner, and also works seamlessly with the new JPMS module system, so if you base your code on ClassGraph, your code will be maximally portable. See the API here.
zapp有一篇精彩的评论,回答了所有这些问题:
new Reflections("my.package").getTypesAnnotatedWith(MyAnnotation.class)
反射似乎比Spring快得多。找到了解决这一差异的特性请求:http://www.opensaga.org/jira/browse/OS-738
这就是为什么在开发过程中使用reflection作为应用程序的启动时间是非常重要的。对于我的用例来说,Reflections似乎也很容易使用(找到一个接口的所有实现者)。
您可以使用Java Pluggable Annotation Processing API编写注释处理器,该处理器将在编译过程中执行,并将收集所有注释类并构建索引文件以供运行时使用。
这是可能进行带注释类发现的最快方式,因为您不需要在运行时扫描类路径,这通常是非常缓慢的操作。此外,这种方法适用于任何类加载器,而不仅仅适用于运行时扫描程序通常支持的urlclassloader。
上述机制已经在ClassIndex库中实现。
使用@IndexAnnotated元注释注释您的自定义注释。这将在编译时创建一个索引文件:META-INF/annotations/com/test/YourCustomAnnotation,列出所有带注释的类。你可以在运行时通过执行以下命令访问索引:
ClassIndex.getAnnotated(com.test.YourCustomAnnotation.class)
Spring有一个AnnotatedTypeScanner类。 这个类内部使用
ClassPathScanningCandidateComponentProvider
该类具有实际扫描类路径资源的代码。它通过使用运行时可用的类元数据来实现这一点。
可以简单地扩展这个类或使用相同的类进行扫描。下面是构造函数定义。
/**
* Creates a new {@link AnnotatedTypeScanner} for the given annotation types.
*
* @param considerInterfaces whether to consider interfaces as well.
* @param annotationTypes the annotations to scan for.
*/
public AnnotatedTypeScanner(boolean considerInterfaces, Class<? extends Annotation>... annotationTypes) {
this.annotationTypess = Arrays.asList(annotationTypes);
this.considerInterfaces = considerInterfaces;
}