Java - Зарегистрируйте все классы, помеченные @MyAnnotation - PullRequest
6 голосов
/ 05 мая 2011

У меня есть аннотация @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?Или любое другое решение?

Любые идеи высоко ценятся, спасибо!

Ответы [ 4 ]

7 голосов
/ 05 мая 2011

Возможно:

  1. Получить все пути в пути к классам. Разобрать System.getProperties().getProperty("java.class.path", null), чтобы получить все пути.

  2. Используйте ClassLoader.getResources(path), чтобы получить все ресурсы и проверить классы: http://snippets.dzone.com/posts/show/4831

4 голосов
/ 05 мая 2011

Не все так просто, но я бы сделал это на языке чистой Java:

  • Получите местоположение Jar вашего приложения из classpath
  • Создайте объект JarFile с этим местоположением, итерируйте по записям
  • для каждой записи, заканчивающейся .class, выполните Class.forName(), чтобы получить объект Class
  • читать аннотацию по рефлексии. Если он присутствует, сохраните класс в List или Set

Аспекты вам здесь не помогут, потому что аспекты работают только с кодом, который фактически выполнен.

Но Обработка аннотаций может быть опцией, создать Процессор, который записывает все аннотированные классы и создает класс, который предоставляет Список этих классов

1 голос
/ 05 мая 2011

Что ж, если ваш AnnotatedClassRegister.registerClass() не нужно вызывать сразу во время создания AnnotatedClassRegister, но он может подождать до первого создания класса, тогда я рассмотрел бы использование Guice TypeListener, зарегистрированного в Matcher, который проверяет, помечен ли класс @MyAnnotation.

Таким образом, вам не нужно искать все эти классы, они будут зарегистрированы непосредственно перед использованием. Обратите внимание, что это будет работать только для классов, экземпляры которых создаются Guice.

0 голосов
/ 23 марта 2013

Я бы использовал staticinitialization() pointcut в AspectJ и изменил бы классы в вашем регистре по мере их загрузки, вот так:

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

Кусок торта, очень простой и элегантный.

...