Я создал этот пример, который совершенно бесполезен, но его простота помогает мне сосредоточиться на важных вещах. Я собираюсь запустить LogEvent из моего действия поддержки, которое будет регистрироваться в java.util.Logger.
Первое, что мне нужно, это создать POJO, который содержит мое сообщение журнала и мой LogLevel.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
public class LogMessage implements Serializable { private final String message; private final Level level; LogMessage(String message, Level level) { this .message = message; this .level = level; } public String getMessage() { return message; } public Level getLevel() { return level; } } |
Теперь, когда у меня есть оболочка для данных, мне нужно что-то, чтобы вызвать событие, и что-то, чтобы его забрать. Первое, что я создаю, — это мой метод запуска события.
Благодаря CDI я могу ввести событие.
1
|
@Inject Event<LogMessage> event; |
Так что нам просто нужно уволить.
1
|
event.fire( new LogMessage( "Log it baby!" , Level.INFO)); |
Теперь событие запускается, и если никто не зарегистрирован, чтобы забрать его, оно исчезает, и мы создаем слушателя. Слушателям нужен метод с одним параметром — универсальным типом, который присваивается предыдущему событию. LogMessage.
1
2
3
4
5
6
|
public class LogListener { private static final Logger LOGGER = Logger.getAnonymousLogger(); public void process( @Observes LogMessage message){ LOGGER.log(message.getLevel(), message.getMessage()); } } |
Аннотация @Observe слушает все события с LogMessage. Когда событие запускается, этот метод будет запущен.
Это очень хороший способ создания слабосвязанного приложения, вы можете разделять тяжелые операции или инкапсулировать менее важные операции в этих прослушивателях событий.
Все это происходит синхронно. Когда мы хотим заменить оператор log медленным вызовом базы данных в таблицу журналов, мы можем сделать нашу работу тяжелее, чем она должна быть.
То, что я ищу, это создать асинхронный вызов. Пока мы поддерживаем EJB, мы можем преобразовать наш Listener в EJB, добавив аннотацию @Stateless поверх него. Теперь это корпоративный бин. Это ничего не меняет в нашей проблеме с синхронизацией / асинхронностью, но EJB 3.1 поддерживает асинхронные операции. Так что, если мы добавим аннотацию @Asynchronous поверх нее. Он будет асинхронно выполнять наш оператор регистрации.
1
2
3
4
5
6
7
8
|
@Stateless @Asynchronous public class LogListener { private static final Logger LOGGER = Logger.getAnonymousLogger(); public void process( @Observes LogMessage message){ LOGGER.log(message.getLevel(), message.getMessage()); } } |
Если мы хотим объединить ведение журнала базы данных и ведение журнала консоли, мы можем просто создать несколько методов, которые прослушивают одно и то же событие.
Это отличный способ создать легкое приложение с очень гибкими компонентами. Альтернативное решение этой проблемы — использовать JMS, но вам не нужна тяжелая конфигурация для такого рода слабой связи.
Ссылка: Java EE6 Events, легкая альтернатива JMS от нашего партнера по JCG Джелле Виктор из блога Styled Ideas .