Riprendiamo ora l'esempio utilizzato nelle lezioni precedenti e cerchiamo di capire come utilizzare in pratica lo IoC Container di Spring. I nostri bean sono rappresentati dalle classi TxtReport
e ReportGenerator
visti in precedenza:
// Classe TxtReport
public class TxtReport implements Report {
String path;
public TxtReport(String path) { this.path = path; }
public void generate(String data) {
System.out.println("genera txt report");
}
public void saveToFile() {
System.out.println("File salvato");
}
}
// Classe ReportGenerator
public class ReportGenerator {
Report report;
public Report generate(String data) {
// report = new TxtReport();
report.generate(data);
return report;
}
public void setReport (Report report) {
this.report = report;
}
}
Creiamo un file bean.xml
dove andremo ad inserire la parametrizzazione:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Indica che il bean 'report' è implementato da TxtReport -->
<bean id="report" class="it.html.spring.report.TxtReport">
<!-- imposta il parametro per il costruttore-->
<constructor-arg value="/report" />
</bean>
<!-- associa il bean 'reportGenerator' al nostro ReportGenerator -->
<bean id="reportGenerator" class="it.html.spring.report.ReportGenerator">
<!-- indica al setter 'report' del reportGenerator di riferirsi ad oggetti -->
<!-- istanziati con il bean 'report' (quindi, in questo caso, TxtReport)-->
<property name="report" ref="report" />
</bean>
</beans>
Analizzando il file di configurazione possiamo notare che è stato chiesto al container di gestire due classi:
it.html.spring.report.ReportGenerator
(con idreportGenerator
)it.html.spring.report.TxtReport
(con idreport
)
Nel file di configurazione sono state anche inserite le direttive per indicare al container come risolvere le dipendenze di queste classi:
- Al bean
report
è stata iniettata, tramite una injection di tipo constructor, una stringa indicante il percorso in cui salvare il report - A
ReportGenerator
è stato iniettato il beanreport
, con una injection di tipo setter.
Infine istanziamo il container e vediamo come interagire con esso per utilizzare i bean configurati:
public class ReportClient {
public static void main(String[] args) {
String data = null;
// ... reperimento dati
BeanFactory ctx = new XmlBeanFactory(new ClassPathResource("beans.xml"));
ReportGenerator gen = (ReportGenerator) ctx.getBean("reportGenerator");
gen.generate(data);
}
}
Una volta istanziato il container è possibile utilizzarlo alla stregua di una factory (da qui il nome BeanFactory
) reperendo i bean attraverso il metodo getBean(nomebean)
.
Per effettuare delle prove è possibile scaricare l'esempio completo (progetto Eclipse)
Come si può ben capire questo modo di operare ci offre enormi vantaggi in termini di riuso dei bean. Se in seguito fosse necessario di un nuovo report che produca file in formato HTML basterà semplicemente scrivere una classe che aderisca all'interfaccia Report
e modificare il bean corrispondente nel file di configurazione.