Architektur: Autowire Colection of Listeners

6 views
Skip to first unread message

Keywan Ghadami

unread,
Sep 25, 2009, 6:30:15 AM9/25/09
to Spring User Group Germany
Hallo,

ich habe an mehreren Stellen in meiner Anwendung Beans die Menge von
Listenern
über Ereignisse Informieren. Die Listener sind dabei selbst Beans so
das die Klasse nichts über die Implementierung der Listener wissen
muss.

Hier ein Beispiel:

@Component
public class FooCaller {

@Autowired(required=false)
private Collection<IFooListener> fooListeners;

void doSomeThings(){
/*... do interesting things ....*/

// inform the listeners
if (fooListeners!= null){
for (IFooListener listener : fooListeners) {
listener.handle();
}
}

}
}

Allerdings bin ich nicht sicher, ob dieses "Pattern" das bestimmt
schon jemand vor mir erfunden hat, so gedacht war.
Es fällt nämlich auf das man zum einen "required" gleich "false"
setzen muss und zum anderen abfangen muss ob fooListeners!= null ist.

Warum gibt die DefaultListableBeanFactory von Spring z.B. nicht eine
leere Liste zurück wenn es keine Listener gibt sondern explizit null?
Selten, aber doch viel zu oft, stehe ich vor dem Problem das die
Reinfolge der Listener entscheidend für einen Anwendungsfall ist. Dann
bin ich gezwungen die Reinfolge der Listener zumindest teilweise hart
zu codieren z.B.:

@Component
public class FooCaller {

@Autowired(required=false)
private Collection<IFooListener> fooListeners;
private IFirstFooListener firstfooListener;

void doSomeThings(){
/*... do interesting things ....*/

// inform the listeners
firstfooListener.handle();
if (fooListeners!= null){
for (IFooListener listener : fooListeners) {
listener.handle();
}
}

}
}

ich hab schon
@Order(...) als Anotation bei den Listenern probiert, leider ohne
Effekt auf die Reinfolge der Listener in der Liste.
Allerdings wäre eine Nummerierung auch nicht die beste Lösung, viel
lieber wäre es mir die Abhängigkeiten der Listener untereinander
beschreiben zu können. Also bei Listener B hinterlegen, dass Listener
A vor ihm aufgerufen werden muss, so das weder der Caller noch
Listener A etwas über die Existens von Listener B zur Compilezeit
wissen müssen.

Bin für jeden Tip dankbar.
Viele Grüße
Keywan Ghadami

Oliver Gierke

unread,
Sep 25, 2009, 9:42:05 AM9/25/09
to Spring User Group Germany
Hallo Keywan,

dafür (Reihenfolge) gibt es bereits ein Ticket im JIRA, was die leere
Liste anstelle von null angeht hab ich noch nicht nachgeschaut. Falls
du allerdings auf Annotationen verzichten und XML verwenden kannst,
ist die Bibliothek Hera (http://hera.synyx.org) vielleicht eine Hilfe.
Damit kannst du mit folgendem Fragment:

<bean class="mein.Client">
<property name="listeners">
<hera:list class="mein.PluginTyp" />
</property>
</bean>

genau das erreichen. Hier bekommst du eine leere Liste, wenn es keine
Bean gibt, die mein.PluginTyp implementiert. Falls es welche gibt,
bekommst du die. Wenn PluginTyp Ordered implementiert bzw.
Implementierungen mit @Ordered annotiert sind, ist die Liste die du
bekommst auch dementsprechend sortiert.

Gruß
Ollie

On 25 Sep., 12:30, Keywan Ghadami <keywan.ghad...@googlemail.com>
wrote:

Oliver Gierke

unread,
Sep 25, 2009, 1:11:02 PM9/25/09
to Spring User Group Germany
Hallo nochmal,

mir sind grad noch ein paar Dinge eingefallen, wie du das auch mit der
Annotation zum fliegen bekommst:

1. Solltest du für die Listener einen Setter bzw. einen
Konstruktorparameter anbieten um die Dependency an der Schnittstelle
ersichtlich zu machen.

2. kannst du dann die Listener auch mit einer leeren Liste
initialisieren (Collections.emptyList()) bzw. auch null-Werte im
Setter/Konstruktor dementsprechendabfangen und auf ne leere Liste
umbiegen.

3. kannst du die Sortierung händisch im Setter/Konstruktor erzeugen
indem du den AnnotationAwareOrderConparator (http://
static.springsource.org/spring/docs/2.5.x/api/org/springframework/core/
annotation/AnnotationAwareOrderComparator.html) einfach selbst benutzt
(Collections.sort(..)).

Klar wäre es nett, wenn die BeanFactory einem das abnehmen könnte,
allerdings sind zumindest die ersten zwei Punkte IMHO gute
Codingpraxis.

Gruß
Ollie

Keywan Ghadami

unread,
Sep 25, 2009, 9:56:42 PM9/25/09
to Spring User Group Germany
Hallo Ollie,
vielen Dank für deine Antwort. Die 3. Punkte von dir sind gut,
allerdings gefällt mir deine Lösung mit hera vom Prinzip her besser,
weil sie die eigentliche Problematik aus der Anwendung in eine
Bibliothek zieht.

Vielleicht kann man die Beanfactory auch durch eine eigene angepasste
Implementierung ersetzen?
Gruß Keywan
Reply all
Reply to author
Forward
0 new messages