Java - 注册所有使用@MyAnnotation注释的类

时间:2011-05-04 21:18:47

标签: java reflection annotations aop guice

我有一个注释@MyAnnotation,我可以使用它注释任何类型(类)。然后我有一个名为AnnotatedClassRegister的类,我希望它注册所有用@MyAnnotation注释的类,以便我以后可以访问它们。如果可能的话,我想在创建AnnotatedClassRegister时自动注册这些类,最重要的是在注释类被实例化之前。

我有AspectJ和Guice供我使用。到目前为止,我提出的唯一解决方案是使用Guice将AnnotatedClassRegister的单个实例注入到一个方面,该方面搜索所有使用@MyAnnotation注释的类,并添加注册此类所需的代码它的构造函数中的类。这个解决方案的缺点是我需要实例化每个带注释的类,以便实际运行AOP添加的代码,因此我无法利用这些类的延迟实例化。

我的解决方案的简化伪代码示例:

// This is the class where annotated types are registered
public class AnnotatedClassRegister {
    public void registerClass(Class<?> clz) {
        ...
    }
}

// This is the aspect which adds registration code to constructors of annotated
// classes
public aspect AutomaticRegistrationAspect {

    @Inject
    AnnotatedClassRegister register;

    pointcutWhichPicksConstructorsOfAnnotatedClasses(Object annotatedType) : 
            execution(/* Pointcut definition */) && args(this)

    after(Object annotatedType) :
            pointcutWhichPicksConstructorsOfAnnotatedClasses(annotatedType) {

        // registering the class of object whose constructor was picked 
        // by the pointcut
        register.registerClass(annotatedType.getClass())
    }
}

我应该采用什么方法来解决这个问题?有没有简单的方法通过反射在classpath中获取所有这些带注释的类,所以我根本不需要使用AOP?还是其他任何解决方案?

非常感谢任何想法,谢谢!

5 个答案:

答案 0 :(得分:7)

有可能:

  1. 获取类路径中的所有路径。解析System.getProperties().getProperty("java.class.path", null)以获取所有路径。

  2. 使用ClassLoader.getResources(path)获取所有资源并检查课程:http://snippets.dzone.com/posts/show/4831

答案 1 :(得分:4)

可靠性并不简单,但我会以纯Java方式进行:

  • 从类路径中获取应用程序的Jar位置
  • 使用此位置创建一个JarFile对象,遍历条目
  • 对于以.class结尾的每个条目,
  • 执行Class.forName()以获取Class对象
  • 通过反射阅读注释。如果它存在,则将该类存储在List或Set

方面不会帮助你,因为方面只适用于实际执行的代码。

annotation processing可能是一个选项,创建一个处理器来记录所有带注释的类,并创建一个提供这些类的列表的类

答案 2 :(得分:0)

好吧,如果你的AnnotatedClassRegister.registerClass()不必在AnnotatedClassRegister创建时立即调用,但它可能要等到第一个实例化的类,那么我会考虑使用Guice {{1注册一个TypeListener,检查一个类是否注释了Matcher

这样,您不需要搜索所有这些类,它们将在使用之前注册。请注意,这仅适用于由Guice实例化的类。

答案 3 :(得分:0)

我会在AspectJ中使用staticinitialization()切入点,并在加载时将类修改到寄存器中,如下所示:

after() : staticinitialization(@MyAnnotation *) {
    register.registerClass(thisJoinPointStaticPart.getSignature().getDeclaringType());
}

一块蛋糕,非常简单而优雅。

答案 4 :(得分:0)

您可以像这样使用 ClassGraph 包:

Java:

try (ScanResult scanResult = new ClassGraph().enableAnnotationInfo().scan()) {
  for (ClassInfo classInfo = scanResult.getClassesWithAnnotation(classOf[MyAnnotation].getName()) {
    System.out.println(String.format("classInfo = %s", classInfo.getName()));
  }
}

斯卡拉:

Using(new ClassGraph().enableAnnotationInfo.scan) { scanResult =>
  for (classInfo <- scanResult.getClassesWithAnnotation(classOf[MyAnnotation].getName).asScala) {
    println(s"classInfo = ${classInfo.getName}")
  }
}
相关问题