2012-04-01 36 views
0

假设我有这个注解搜索特定注释类型的所有实例

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface Name 
{ 
    String value(); 
} 

这是怎么回事如下

@Name("name1") 
public static Foo foo = new Foo(); 

我的这些倍数在我的项目源文件使用。是否有一种相当简单的方法来搜索和收集所有那些之前有@Name的“foo”? 换句话说,我想写一个方法,将返回一个Set<Foo>包含这些。

谢谢!

+0

在java中?使用find + grep – ControlAltDel 2012-04-01 00:16:11

+0

@ user1291492,使用unix cmd行应该非常容易,保留时间为RUNTIME。该方法可能会或可能不会访问源代码。 OTH,也许这个类文件是可以greppable的。 – emory 2012-04-01 05:18:15

+0

稍有偏离主题,但你为什么要'Set '。有一个'Map '或名称的重点似乎更有意义。 – emory 2012-04-01 05:20:49

回答

2

我对其他人建议的类路径扫描程序并不熟悉。他们看起来像一个强大的,如果不是理想的解决方案。

如果您可以控制源,那么您可以使用注释处理。

创建一个注释处理器,该注释处理器将创建一个具有静态成员Map<String,Foo>的类 - MapClass。注释处理器每次遇到@Name注释时,都会将其添加到源代码MapClass。当它完成处理注释时,它将具有与硬编码地图相同的效果。

注释处理发生在编译期间。如果项目中的某些类不是由您编译的。例如,如果其他人编译一些类并给你一个罐子,那么它不会很容易工作。但是,如果所有的类都由您编译,那么它不应该是一个问题。

要创建注释处理器,请扩展AbstractProcessor。您需要使用@ SupportedAnnotationTypes ("Name")批注注释您的课程(确保名称是注释的完全限定名称。

覆盖process方法。 process有两个参数:annotationsroundEnvannotations只是这个特定处理器支持的一组注释 - 在你的情况下它应该是(Name)。 roundEnv是一个有用的工具类。

迭代annotations中的一个注释。使用roundEnvgetElementsAnnotatedWith。这应该给你带有@Name注释的所有元素的集合。

AbstractProcessor还有另一个实用程序成员 - processingEnv。使用其getFiler方法createSourceFile

然后你必须稍微修改一下你的编译。您必须分别在其他课程之前编译处理器。在编译处理器并编译其他类之后,必须告诉编译器关于处理器的信息。如果您正在使用命令行,则可以添加-processorpath /path/to/processor/class[es]-processor qualified.name.of.processor

这种方法优于类路径扫描程序的优点是,所有事情都发生在编译时。例如,如果您不小心将一个@Name注释添加到Bar元素,则可以让处理器发出编译时错误(如果希望处理器可以忽略它)。然后你可以在产品发货前修好它。使用类路径扫描程序时,抛出的任何错误都是运行时错误 - 用户将看到。

这种方法的缺点是,一切都发生在编译时。这使得向项目动态添加类变得更加困难。

+0

这听起来像我需要的。但是注释处理器到底是什么样的?我不确定它是如何“遇到”@Name注释的?它不会需要做一些扫描找到那些? – user113454 2012-04-01 06:40:31

+0

请您详细说明一下吗?谢谢 – user113454 2012-04-01 07:58:46

+0

@ user1064918我希望有所帮助。我认为最大的区别是,类路径扫描器更强大 - 它只会工作。但是如果你的项目合适,使用注释处理器可能更合适。 – emory 2012-04-01 17:32:18

0

不是真的(不是来自代码)。 一个解决办法是把他们都在一个类,然后在类的Field S(getFields())迭代,并检查Annotation S(getAnnotation()

1

你需要的是一个classpath的扫描仪。我用Metapossum Scanner(它赢得了,因为它在mvn回购)扫描注释类,但我不认为它会扫描注释的字段。

我看着的其他选项是Reflections。我没有使用反射,只研究它。该文档有一个getFieldsAnnotatedWith查询,这似乎是你需要的。

要预先警告,Classpath扫描仪是非常流行的,并且在您的Classpath中拥有更多的功能。

0

你可能想看看Scannotation!它可能会解决你的问题!

Scannotation是一个Java库,它从一组.class文件创建一个注释数据库。这个数据库实际上只是一组索引,用于索引使用哪些注释以及哪些类正在使用它们。

PS .: VRaptor framework内部使用!

相关问题