Autowiring a Spring

Dnes chci psát o autowiringu ve Springu. Nejde o žádnou novinku. Je to funkcionalita, která je ve Springu už od první verze, ale moc jsem ji nepoužíval, protože se mi nelíbila. Nedávno jsem na ni ale změnil názor.

Začněme od toho co to je autowiring. Standardní Spring konfigurace vypadá takto:

<beans>
	<bean id="foo" class="net.krecan.blog.FooImpl1">
		<!--  Some configuration -->
	</bean>
	<bean id="bar" class="net.krecan.blog.Bar">
		<property name="foo" ref="foo"/>
	</bean>
</beans>

Do beanu bar, injektujeme instanci sigletonu foo. Autowiring spočívá v tom, že můžeme Springu říci, aby si závislosti automagicky vyřešil sám.

<beans default-autowire="byType">
	<bean id="foo" class="net.krecan.blog.FooImpl1">
		<!--  Some configuration -->
	</bean>
	
	<bean id="bar" class="net.krecan.blog.Bar"/>
</beans>

Do tagu beans jsem přihodil atribut default-autowire, kterým říkám, ať propojuje beany podle typu (existují i jiné metody viz. zde). Spring si prohlédne všechny nadeklarované beany, projde si jejich set metody a podle typu pozná, že má do beanu bar vložit bean foo.

Ty zvídavější jistě napadne, co se stane, když mapování není jednoznačné.

<beans default-autowire="byType">
	<bean id="foo1" class="net.krecan.blog.FooImpl1">
		<!--  Some configuration -->
	</bean>
	<bean id="foo2" class="net.krecan.blog.FooImpl1">
		<!--  Some configuration -->
	</bean>
	<bean id="bar" class="net.krecan.blog.Bar"/>
</beans>

V tomto případě Spring okamžitě vyhodí výjimku. Ani teď se Autowiringu nemusíme úplně vzdát, ručně musíme vyřešit jenom nejednoznačné závislosti, ostatní, jednoznačné beany se spojí samy.

Když jsem autowiring viděl poprvé, tak se mi zdála hrozně křehký a náchylný na chybu. Proto jsem si beany hezky spojoval ručně a byl jsem spokojen. Nedávno jsem ale přepisoval projekt z EJB 3 do Springu. Smazal jsem všechny EJB anotace a chystal jsem se napsat Spring konfigurační soubor. Po prvních pár beanech mi došlo, že to bude strašlivá práce. Zkusil jsem zapnout autowiring a všechno najednou jelo jako po másle. Stačilo mít jenom ve Spring configu vyjmenované všechny použité beany a doplnit pár chybějících set metod.

Nejen, že mi to ušetřilo práci při migraci, ohromě to i usnadňuje refaktoring. Když přesouvám nebo přidávám DAO do servisní vrstvy, vůbec se nemusím starat o konfiguraci. Změním kód a to je všechno. Myslím si tedy, že ve Springu 2 je autowiring dobrá volba. Pokud používate Spring 1 můžete narazit na problémy s ručně konfigurovanými proxy objekty. Ty vám v některých případech mohou způsobit nejednoznačnost mapování tím, že v kontextu bude vidět jak původní beana, tak obalující proxy, která implementuje stejné rozhraní. Ve Springu 2 se dají proxy snadno generovat automaticky, takže tento problém je méně pravděpodobný.

11 thoughts on “Autowiring a Spring

  1. Lukáš

    Jen čistě ze zvědavosti, jaký byl důvod přepisu aplikace z EJB 3.0 na Spring? Nějaký specifický, nebo jen osobní preference? 🙂

  2. Petr

    Já osobně nepoužívám auto-wiring pro produkční kód – možná je to jen výmluva, ale chci to mít vše pod svojí kontrolou. Jinak ale v testování používám auto-wiring rád.

  3. Tomáš

    Zajímavé, ale asi bych se toho přece jen někde hluboko v duši trošku bál 🙂 Neexistuje třeba nějaký způsob jednorázového “vygenerování” wiring XML ve stylu “teď nechám spring ať to jednorázové zkusí zautowirovat a vyplivne XMLko, které si ručně zreviduju a zintegruju se svým XMLkem”? Pokud takový tool neexistuje, hodil by se 😉

  4. Lukáš Křečan Post author

    to Lukáš: Důvod pro přepsanání EJB do Spring byl takový, že chceme danou aplikaci spouštět pod Resinem. I před tím to běželo za pomocí Pitchforku, jenom se mi tam nelíbila ta vrstva navíc.

  5. Lukáš Křečan Post author

    Chápu vaše obavy, i já jsem z toho měl divný pocit. Když se nad tím ale člověk zamyslí, tak se kvůli autowiringu nemůže nic špatného přihodit. Schválně, napište mi tu někdo něco, co se může kvůli autowiringu stát a kvůli ruční konfiguraci ne.

  6. Honza Novotný

    No já autowiring v produkci taky nepoužívám, ale řekl bych že je to hodně, kvůli omílání této praktiky v best practices (např. http://www.onjava.com/pub/a/onjava/2006/01/25/spring-xml-configuration-best-practices.html, http://lijinjoseji.wordpress.com/2007/09/28/spring-framework-best-programming-practices-part-4/).
    Při správném rozdělení aplikace na moduly, kde každý modul má jen omezenou velikost konfigurace v application contextu, by možná už stálo za přehodnocení používání autowiringu. Jako hlavní výtku všechny články uvádějí, že takováto konfigurace je méně čitelná. Faktem je, že pokud je ve springu uvedeno, že se má nějaká beana nasetovat do nějaké property, člověk nemusí nad ničím hloubat – vše je vidět už na první pohled. Autowiring toto zcela jistě stěžuje.

  7. Karlos

    Pod Resinem funguje auto-wiring? Už je to celkem dávno, ale pod resinem nám aplikace přestala fungovat, v tomcatu normálně běžela. Vyřešilo se to tak, že se auto-wiring vypnul. Tomcat do produkčního prostředí nebrat… 🙂

  8. bady

    Zdá se mi že autowiring je jednoduchost zápisu na úkor čitelnosti. Z konfiguráku už není na první pohled jasné, na čem daná beana závisí. To mě při čtení dost irituje, protože najednou musím lézt do zdrojáku a už ztrácím kontext. S tím souvisí i podpora v IDE (aspoň Spring IDE se na autowiring nechytá).

    Pak ještě konkrétní rýpnutí, kdy může autowiring selhat. Mám beanu A která závisí na B. B je v jiném konfiguráku (sestavuju různé sady konfiguráku podle prostředí). Protože nemám explicitně řečenou závislost na B, nemůžu si být jistý že tam někde ta B je definovaná, mohla se stát např. chyba že se ten druhý konfigurák nenačetl, atd. Výsledkem je že se B do A nenainjektuje a bude tam null. Tohle jde řešit přes anotaci Required, ale není už pak skoro jednodušší tu závislost explicitně definovat?

  9. Vasek

    Jenom ohledně té podpory v IDE, IntelliJ IDEA ve verzi 7 autowiring podporuje, jak při editaci XML configurace, tak umí autowired závislosti zobrazit v grafickem náhledu.
    Taky vám vynadá, pokud nelze autowired závislosti jednoznačne namapovat. Nemusíte čekat na Spring výjimku při běhu aplikace.
    Pokud se časem rozhodnete závislosti vyjádřit explicitně, i s tím vám pomůže – stačí Alt-Enter.
    Takže já autowired závislosti používám a nebezpečí v nich nevidím.

  10. Pingback: Java drobečky » Blog Archive » Resin a Spring autowiring

Comments are closed.