java аннотации - Как создать пользовательскую аннотацию с кодом




рефлексия аннотация (3)

Я хотел бы создать свою собственную аннотацию. Моя структура - автономное Java-приложение. Когда кто-то аннотирует свой класс pojo, «скрытый» код будет запускать методы.

Например, сегодня в Java EE имеется аннотация @MessageDriven . И когда вы комментируете свой класс с помощью @MessageDriven и, кроме того, реализуете интерфейс MessageListener, есть код, который будет вызывать onMessage(Message msg) . когда сообщение поступает из очереди / темы.

Как создать аннотацию ( @MyMessageDriven ), которая может быть добавлена ​​в pojo, а также реализовать MyCustomMessageListener .

Результат, который я желаю, является триггером «скрытого» кода (моего), который вызовет метод реализованного интерфейса (точно так же, как он работает с образцом, который я написал ниже).


Answers

создайте аннотацию примерно так:

 public @interface MyMessageDriven{
 }

И у вас есть интерфейс, который может применять аннотацию следующим образом:

public interface MyMessagListener {

    public void message();
}



@MyMessageDriven  
public class MyMessage implements MyMessagListener  {
   public void message(){
     System.out.println(" I am executed")
   }
} 

Загрузите вышеприведенный класс с помощью загрузчика классов и с помощью отражений проверьте, что аннотация является прерентной.

если он присутствует, используйте загруженный экземпляр для его выполнения.

  Object obj = ClassLoader.getSystemClassLoader().loadClass("MyMessage").newInstance();
  MyMessagListener mml =  (MyMessagListener) obj;
  mml.message();

Реализация прослушивателя вы можете поместить в класс MyMessage или какой-либо другой класс, который реализует MessageListener.

В этом случае необходимо обеспечить реализацию для message() того, что он собирается делать.

Но этот класс должен быть загружен, и более важным является то, как загружается ваш класс MyMessage.

Это основано на метаданных, присутствующих в классе MyMessage. Аналогичным образом в сценарии реального времени это так.

Аннотирование - это метаданные для класса, который говорит на основе предоставленных данных, что-то делать. Если эти метаданные не присутствуют в классе MyMessage, вам не нужно выполнять метод message() .

Надеюсь, что это поможет вам.


Я рекомендую прочитать эту запись в блоге (моментальный снимок на archive.org) до момента, когда автор помнит, что у него есть доступ к функции проверки компонентов Spring.

Первоначальная проблема заключается в проверке пути к классу для поиска классов с пользовательской аннотацией. Как только это будет сделано, у вас есть объекты в вашем автономном приложении, через которые с помощью object.getClass().getAnnotations() вы можете затем добавить слушателей или настраиваемое поведение, которое необходимо добавить к объектам, содержащим пользовательские аннотации.

Допустим, у вас есть следующая пользовательская аннотация:

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMessageDriven {}

И вы используете его в своем приложении:

@MyMessageDriven
public class MyObject {}

Теперь, в соответствующем месте в вашем приложении, вы должны иметь способ выдавать все классы, на которых есть MyMessageDriven :

Set<Class<?>> findAllMessageDrivenClasses() {
  final StopWatch sw = new StopWatch();
  sw.start();
  final Reflections reflections = new Reflections("org.projectx", new TypeAnnotationsScanner());
  Set<Class<?>> allMessageDrivens = reflections.getTypesAnnotatedWith(MyMessageDriven.class); // NOTE HERE
  sw.stop();
  return allMessageDrivens;
}

Имея это, я предполагаю, что в вашем приложении есть точка, в которой (1) у вас есть доступ к объектам в вашем приложении, или (2) на всех объектах приложения присутствует шаблон посетителя или итератора. Итак, в какой-то момент я предполагаю, что у нас есть все целевые объекты как objects :

Set<Class<?>> msgDrivenClasses = findAllMessageDrivenClasses();
for (Object o : objects) {
  if (msgDrivenClasses.contains(o.getClass()) {
    invokeTheMessageListener(o);
  }
}

С другой стороны, должна существовать некоторая реализация MyMessageListener которая доступна, когда найдены объекты, имеющие MyMessageDriven :

void invokeTheMessageListener(Object o) {
  theMessageListener.onMessage(o);
}

Этот ответ настроен на запись в блоге, поэтому, пожалуйста, обратитесь к блогу для настройки библиотек. И, наконец, не в последнюю очередь, это пример кода для проблемы, и он может быть реорганизован на более совместимый с рисунком и элегантный стиль.

Обновление : существует требование, чтобы целевые объекты были осведомлены о своих собственных слушателях. Поэтому я бы предложил следующий подход. Давайте MyMessageListenerAware интерфейс MyMessageListenerAware :

interface MyMessageListenerAware {
  MyMessageListener getMyMessageListener();
}

// and this is the original MyMessageListener
interface MyMessageListener {
  void onMessage(Object o);
}

Теперь целевые объекты должны реализовать указанный выше интерфейс:

class MySampleObject implements MyMessageListenerAware {

  public MyMesssageListener getMyMessageLisener() {
    return mySampleObjectImplementationOfMyMessageListener;
  }

}

Имея это, метод invokeTheMessageListener становится следующим:

void invokeMessageListener(Object o) {
  if (o instance MyMessageListenerAware) {
    MyMessageListener l = ((MyMessageListenerAware) o).getMyMessageListener();
    l.onMessage(o);
  }
}

Хотя , я настоятельно рекомендую прочитать о шаблоне Visitor или Strategy . То, что вы намереваетесь сделать, похоже на то, что вам нужно, чтобы определенные объекты реагировали / действовали / обрабатывались с общим объектом / событием в приложении, но каждый со своей собственной интерпретацией / алгоритмом / реализацией.


Поскольку этот вопрос довольно старый, меня удивляет, что никто не предложил простейшую форму:

List<Element> arraylist = Arrays.asList(new Element(1), new Element(2), new Element(3));

Начиная с Java 5, Arrays.asList() принимает параметр varargs, и вам не нужно явно строить массив.





java dependency-injection interface annotations