L'uso della Constructor Dependency Injection può portare alla creazione di dipendenze cicliche tra i beans. Ad esempio se un oggeto A ha bisogno per essere instanziato di un oggetto B, ma allo stesso tempo l'oggetto B ha bisogno dell'oggetto A, si crea un dipendenza che non può essere risolta usando la Constructor Dependency Injection.
In casi come questi si deve usare la Setter Dependency Injection che è molto simile alla Constructor ma la differenza sta nel fatto che le dipendenze vengono iniettate dopo che l'oggetto è stato instanziato. Vediamo un esempio:
public class Bean2 {
private GenericService genericService;
public void setGenericService(GenericService genericService) {
this.genericService = genericService;
}
public GenericService getGenericService() {
return genericService;
}
/**
* Business logic.............
*/
}
nell'applicationContext.xml
<bean id="setterBean" class="it.mrwebmaster.di.setter.Bean2">
<property name="genericService" ref="genericService" />
</bean>
Oltre a risolvere il problema delle dipenze circolari la Setter Dependency Injection consente anche di riconfigurare a runtime i beans, per questi motivi viene preferita alla Constructor. Alcune scuole di pensiero però dicono che l'ottimo sarebbe quello di usare entrabe: la Constructor per le dipendenze necessarie e la Setter per quelle opzionali. Si consiglia comunque di usare la Setter poichè è molto raro che ci siano delle dipendenze opzionali.
Oltre all'uso di base della DI ci sono altre funzionalità che Spring offre, ad esempio si possono iniettare stringhe vuote o campi null:
<!-- NULL VALUE 1 -->
<bean id="nullBean1" class="it.mrwebmaster.di.constructor.bean" factory-method="createBean">
<constructor-arg value="0" type="java.lang.Integer" />
<constructor-arg value="" type="java.lang.String" />
<constructor-arg type="it.mrwebmaster.di.constructor.GenericService"><null/></constructor-arg>
</bean>
<!-- NULL VALUE 2 -->
<bean id="nullBean2" class="it.mrwebmaster.di.setter.Bean2">
<property name="genericService"><null/></property>
</bean>
Spring offre anche una gestione delle Collection del tipo List, Set, Map, e Properties attraverso i tag list, set, map, e props:
public class CollectionBean {
private List<GenericService> beanList;
private Properties beanProps;
private Set<String> beanSet;
private Map<Integer, String> beanMap;
/**
* business logic......................
*/
public List<GenericService> getBeanList() {
return beanList;
}
public Map<Integer, String> getBeanMap() {
return beanMap;
}
public Properties getBeanProps() {
return beanProps;
}
public Set<String> getBeanSet() {
return beanSet;
}
public void setBeanList(List<GenericService> beanList) {
this.beanList = beanList;
}
public void setBeanMap(Map<Integer, String> beanMap) {
this.beanMap = beanMap;
}
public void setBeanProps(Properties beanProps) {
this.beanProps = beanProps;
}
public void setBeanSet(Set<String> beanSet) {
this.beanSet = beanSet;
}
}
nell'applicationContext.xml
<!-- COLLECTION BEAN -->
<bean id="collectionBean" class="it.mrwebmaster.di.collection.CollectionBean">
<!-- LIST -->
<property name="beanList">
<list>
<ref bean="genericService"/>
</list>
</property>
<!-- PROPERTIES -->
<property name="beanProps">
<props>
<prop key="prop1">value1</prop>
<prop key="prop2">value2</prop>
<prop key="prop3">value3</prop>
</props>
</property>
<!-- SET -->
<property name="beanSet">
<set>
<value>a</value>
<value>b</value>
</set>
</property>
<!-- MAP -->
<property name="beanMap">
<map>
<entry key="1" value="value1" />
</map>
</property>
</bean>
Si lascia al lettore l'approfondimento su altre questioni come il merge delle collection, gli inner beans e i collaborators.