Такие запросы с временным интервалом могут потреблять много ресурсов на сервере, а также вызывать больший сетевой трафик, чем фактически необходимо. Хотя Java поддерживала шаблон Observer начиная с 0-го дня, он всегда считается не самой лучшей реализацией (посмотрите на Observer и Observable ). Нахождение в мире JavaEE может даже усложнить ситуацию. Однако JavaEE6 поставляется с альтернативой.
JavaEE6 предлагает аннотацию @Observable как простую готовую реализацию Observer Pattern. Давайте посетим предыдущий пост и расширим его, чтобы использовать наблюдателей.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
package com.devchronicles.observer;import javax.ejb.Stateless;import javax.ejb.TransactionAttribute;import javax.ejb.TransactionAttributeType;import javax.enterprise.event.Event;import javax.inject.Inject;/** * * @author Murat Yener */@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public class EventService { @Inject private String message; @Inject Event<String> event; public void startService(){ System.out.println("start service call "+message); event.fire("this is my "+message); System.out.println("done..."); }} |
Класс EventService будет внедрен в объект Event типа String, который можно использовать для запуска объектов String. Если вы не читали предыдущий пост, объект сообщения является строкой, которая будет создана фабрикой и введена в класс EventService. Чтобы упростить его, вы можете просто ввести любую строковую константу в переменную с именем message.
Поскольку мы уже закончили с наблюдаемой частью, теперь пришло время создать наблюдателя для прослушивания наших событий.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
package com.devchronicles.observer;import javax.ejb.Stateless;import javax.enterprise.event.Observes;/** * * @author Murat Yener */@Statelesspublic class EventObserver { public void doLogging(@Observes String message){ System.out.println("Observed:"+message); }} |
Аннотация «Обзоры» помечает метод как наблюдатель для событий String. Если вы запустите сервер и запустите метод обслуживания start, вы поймете, как волшебным образом строка будет введена в класс EventService и чем она будет запущена там, где ее будет предупреждать (наблюдает) класс EventObserver. Удивительно, но это все, что вам нужно для реализации шаблона наблюдателя в JavaEE6.
Как было показано ранее, JavaEE6 предлагает простой способ реализации шаблона Observer. После публикации поста я получил несколько вопросов о том, как различать строковые типы, которые запускаются и наблюдаются.
Хотя в реальных сценариях вы, вероятно, не будете стрелять и наблюдать простые строки, а будете иметь собственные объекты, которые будут наблюдаться по их типу, все же довольно легко различить объекты одного типа и настроить разных наблюдателей для их прослушивания.
Сначала давайте начнем с части, чтобы дифференцировать простые строки.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package com.devchronicles.observer;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import javax.inject.Qualifier;/** * * @author Murat Yener */@Qualifier@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD,ElementType.PARAMETER})public @interface MyEvent { Type value(); enum Type{ LOGGING, MESSAGE } } |
Приведенный выше интерфейс будет действовать как аннотация, чтобы пометить строку, которую нужно запустить, а затем наблюдать, просто пометив соответствующие части.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package com.devchronicles.observer;import javax.ejb.Stateless;import javax.ejb.TransactionAttribute;import javax.ejb.TransactionAttributeType;import javax.enterprise.event.Event;import javax.inject.Inject;/** * * @author Murat Yener */@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public class EventService { @Inject private String message; @Inject @MyEvent(MyEvent.Type.LOGGING) Event<String> event; @Inject @MyEvent(MyEvent.Type.MESSAGE) Event<String> anotherEvent; public void startService(){ System.out.println("start service call "+message); event.fire("this is my "+message); System.out.println("done..."); anotherEvent.fire("done with the service!"); }} |
Мы просто добавляем аннотацию MyEvent с нужным типом и позже запускаем события, как мы делали раньше. Части, помеченные красным, — это все, что мы добавили в пример из предыдущего поста.
Теперь давайте аннотируем часть наблюдателя. Опять же, мы просто добавим красные части к предыдущему примеру.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.devchronicles.observer;import javax.ejb.Stateless;import javax.enterprise.event.Observes;/** * * @author Murat Yener */@Statelesspublic class EventObserver { public void doLogging(@Observes @MyEvent(MyEvent.Type.LOGGING) String message){ System.out.println("Observed:"+message); } public void doLogging(@Observes @MyEvent(MyEvent.Type.MESSAGE) String message){ System.out.println("Observed another type of message:"+message); }} |
Это все, что вам нужно, чтобы различать даже объекты одного и того же типа для наблюдения.
Ссылка: JavaEE Revisits Design Patterns: Observer , JavaEE Revisits Design Patterns: Observer, часть 2 от нашего партнера по JCG Мурата Йенера в блоге Developer Chronicles .