Spring-02: Inversion of Control con configurazione bean via XML

S

INTRODUZIONE

Ciao coders,

nel precedente articolo, che trovate al seguente LINK , abbiamo introdotto Spring e concetti come IOC e Dependency Injection. In questo articolo mostreremo che con Spring Boot è anche possibile configurare il contesto dell’applicazione con file xml, metodologia piu’ familiare per chi ha lavorato molti anni con le prime versioni di Spring o con JEE.  Gli obbiettivi di questo articolo sono quindi :

  • Riscrivere l’esercizio dell’articolo precedente utilizzando file xml per la configurazione dell’IOC  ( per chi non l’ha letto corra a leggerlo LINK … e’ propedeutico per comprendere a pieno questo articolo)
  • Best practices su Spring per la metodologia di configurazione dei bean ( XML o Annotation ?!)

xml config

Nell’articolo precedente abbiamo realizzato il nostro primo applicativo Spring ( link al repository ) :

  • Abbiamo definito un bean lista di stringhe utilizzando l’annotation @Bean all’interno di una classe @Config ( in realta’ la nostra classe usava l’annotation @SpringBootApplication la quale importa anche @Config);
  • Abbiamo definito il componente ReportExec il quale sara’ istanziato nell container di Spring grazie alla annotation @Component e al component scan attivo.

Per chi e’ un “fan” dei file di configurazione xml  è anche  possibile configurare i bean dell’ IOC container di Spring utilizzando file xml di configurazione anziché’ java annotation come @Bean e @Component.  Proviamo a riscrivere l’esempio precedente configurando il framework con un file xml di config.

Il sorgente di questo esercizio o lo trovate al seguente LINK ma cercherò’ di guidarvi passo passo per permettervi di creare il progetto in autonomia.

  • Procedete ad inizializzare un nuovo progetto Spring con Spring initializer senza specificare nessuna dipendenza.
  • Creiamo di nuovo il package components e riportiamo all’interno di esso una copia della classe ReportExec andando a rimuovere l’annotation component.
public class ReportExec {


    private List<String> studentsList;

    public List<String> getStudentsList() {
        return studentsList;
    }

    public void setStudentsList(List<String> studentsList) {
        this.studentsList = studentsList;
    }

    public void execute(){
        System.out.println("I nostri studenti sono");

        for(String student : studentsList){
            System.out.println("Nome:"+student);

        }
    }
}
  • Modifichiamo il codice della classe annotata come SpringBootApplication come nell’esempio precedente
@SpringBootApplication
@ImportResource("classpath:app-config.xml")
public class DemoDiLesson2Application implements ApplicationListener<ApplicationReadyEvent> {

  @Autowired
  ReportExec reportExec;

  public static void main(String[] args) {
    SpringApplication.run(DemoDiLesson2Application.class, args);
  }

  @Override
  public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
    reportExec.execute();

  }
}

Come si può’ notare a differenza dell’articolo precedente e’ presente la nuova annotation ImportResource la quale segnala a Spring  di importare la configurazione di beans riferite dal file app-config.xml  ( NB: è possibile importare più file xml). Come facilmente si può intuire  puoi definire i tuoi bean sia all’interno di una o più  classi @Config che in appositi file xml. Procediamo quindi nella creazione  del file app-config.xml ; Utilizzando la  facility del vostro IDE avete modo di creare un file pre-configurato. Ad esempio con IntelliJ cliccando sulla cartella resources con il tasto destro del mouse hai a disposizione tra le tante opzioni quella per creare un file xml di configurazione Spring.

Il file appena creato avra’ la seguente struttura.

<?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.xsd">



</beans>

All’interno del tag xml  beans  e’ possibile definire uno o più’ bean che Spring in fase di runtime instanzierà nell’IOC Container; Seguendo la documentazione ufficiale andiamo adesso a definire i bean del nostro esercizio:

<?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.xsd">


    <bean id="studentList" class="java.util.ArrayList">
        <constructor-arg>
            <list>
                <value>pippo</value>
                <value>pluto</value>
            </list>
        </constructor-arg>
    </bean>

    <bean id="reportExec" class="it.italiancoders.demodilesson2.components.ReportExec">
        <property name="studentsList" ref="studentList"/>
    </bean>


</beans>

Come facilmente si può intuire in questo file ci sono la configurazione dei Bean che Spring dovrà instanziare:

  • Definizione di un bean studentList di tipo ArrayList inizializzato utilizzando il costruttore passando una lista di due elementi “pippo” e “pluto”;
  • Definizione del bean reportExec inniettando la properietà studentsList  di tale bean con il bean di id studentList definito allo step precedent.

E’ possibile attivare la component scan anche da xml, aggiungendo la seguente direttiva

<context:component-scan base-package="it.italiancoders"/>

ma noi non lo faremo perché stiamo ancora facendo uso di una classe di configurazione annotata con @SpringBootApplication (il main del nostro progetto).

La struttura finale del progetto e’ la seguente

Eseguendo il main della nostra applicazione l’output sara’ il medesimo della lezione precedente.

I nostri studenti sono
Nome:pippo
Nome:pluto

Il progetto funzionante lo trovate al LINK : potete procedere a clonare o aggiornare a Repository GITHUB  ufficiale di Spring-Italiancoders

git clone https://github.com/dario-frongillo/italiancoders-spring-tutorial

L’esempio funzionante di questo articolo è contenuto nella folder folder 2-ioc_di_ext.

XML VS ANNOTATION

Chiariamo innanzitutto che non vi è una risposta assoluta se sia meglio utilizzare annotation o configurare un xml per la definizione dei bean.. e’ questione di gusti. Tuttavia Spring Boot e’ fortemente progettato per lavorare con le annotation, garantendo comunque la possibilità’ di configurare qualsiasi settings anche utilizzando direttive contenute in appositi file  xml di configurazione del context. Quindi quale approccio è consigliato ? Sicuramente un apporccio  “misto”  ma con cognizione di causa! Io normalmente mi comporto così:

  • Utilizzo le annotazioni per tutto quello che definisce la struttura principale dell’applicazione. Qualsiasi cosa che necessiti di un cambio di codice va bene come annotazione.
  • Preferisco alla lunga far risolvere le dipendenze dei miei bean con la dependency injection e non risolvendo  le dipendenze manualmente nei file xml ( lunga vita a @Autowired)
  • Utilizzo il component scan anziche’ creare manualmente un bean alla volta nel file xml. Su questo punto in rete trovate opinioni discordanti. Definire un bean alla volta  in file xml e’ particolarmente verboso ma ha il vantaggio di avere la lista dei bean centralizzati in uno o piu’ file xml. Tuttavia come ho chiaramente anticipato il framework Spring Boot ha preso la via delle annotation come prima soluzione per alcuni importanti e noti vantaggi:
    • Java è type safe. Il compilatore riporterà errori in fase di compilazione se stai configurando male a causa di errori di battitura o tipi di dato incompatibili. Con Xml non hai nessun check anche se gli IDE più evoluti fanno un minimo di controllo di coerenza.
    • XML è prolisso, quindi i file di configurazione diventano grandi. È una buona cosa dividerli e quindi anche utilizzando XML si perde il vantaggio di centralizzare la configurazione dei bean.
    • Per quanto riguarda la configurazione dei bean in più file xml,  non è possibile navigare tra diversi file XML. Se vuoi sapere dove viene definito Spring bean pippo, dovrai fare affidamento sulla ricerca full-text.
    • Un altro punto a favore delle annotation è la poca intuitività dei file xml di Spring;  Java lo conoscono anche i “muri”  perché dovrei usare un linguaggio diverso per le configurazioni? Sembra davvero naturale definire i bean dal java piuttosto che complicarsi per esprimere la definizione di un bean in XML.
  • Utilizzo le configurazioni basate su XML quando so’ che potrei dover modificare il comportamento di un bean senza dover compilare  nuovamente il codice oppure semplicemente perche’ voglio separare dal codice delle mie classi stringhe di configurazione come ad esempio l’url di un database o parametri di configurazione. Come vedremo in una delle prossime lezioni e’ possibile rendere esterno al war/jar dell’applicazione uno o piu’ file xml di configurazione.  Alcuni esempi di situazioni in cui utilizzo la configurazione xml:
    • bean di configurazione del datasource ( parametri di connessione al db)
    • bean di integrazione a servizi esterni dove magari trale property specificate e’ presente anche l’ip e la porta di tale servizio ( es configurazione della connessione ad ActiveMQ o un FTP). Ricordatevi le stringhe  hard-coded sono sempre’ una pessima soluzione.
  • Anche se faccio uso di xml definisco le costanti (es. l’url di un database)  in diversi file di properties facendo uso dei profiles una importante features di Spring la quale permette di separare la configurazione dell’applicazione nei diversi ambienti ( ad es. Produzione e Test punteranno a DB differenti). Una volta definita la property la riferisco all’interno del file xml. ( Su questo punto tranquilli farò un articolo ad hoc )

CONCLUSIONI

In questo breve articolo abbiamo realizzato l’esempio dell’articolo precedente utilizzando file xml di configurazione anzichè java annotation. Inoltre ho provato a dare una risposta alla domanda “XML vs Java Annotation” che almeno una volta ti sarai fatto programmando in Spring.

Nel prossimo articolo andremo a spiegare in dettaglio tutte le opzioni di configurazione dei nostri bean in modo da completare la panoramica su Dependency Injection e IOC.

A proposito di me

Dario Frongillo

Software architect con un forte background in Java, Architettura REST, framework Spring , Database Design,progettazione e sviluppo di SPA e RIA Web application con framework Javascript. Attualmente mi occupo di sviluppo soluzioni software in ambito Banking e Finance: in particolare progettazione e sviluppo di applicativi web based per la realizzazione di sistemi di trading, interfacce con i mercati finanziari e di servizi real time.

Di Dario Frongillo

Gli articoli più letti

Articoli recenti

Commenti recenti