Вопрос по dependency-injection, java – Как создать пользовательскую аннотацию с кодом позади

35

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

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

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

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

Какой контейнер или бизнес-каркас вы используете? nobeh
Это отдельное Java-приложение. rayman

Ваш Ответ

2   ответа
10

 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() метод.

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

Error: User Rate Limit Exceeded rayman
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded rayman
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
33

эта запись в блоге (снимок на 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);
}

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

Update: Есть требование, чтобыtargeted объекты должны знать своих слушателей. Итак, я предлагаю следующий подход. Давайте иметь интерфейс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);
  }
}

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

Error: User Rate Limit Exceeded rayman
Error: User Rate Limit Exceeded rayman
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded rayman

Похожие вопросы