Anda di halaman 1dari 28

Scuola Politecnica e delle Scienze di Base

Corso di Laurea in Ingegneria Informatica

Elaborato finale in Programmazione II

Il framework Spring

Anno Accademico 2015-2016

Relatore:
Ch.mo prof. Marcello Cinque

Candidato:
Pasquale Tremante
matr. N46001295
Indice
1 Introduzione 2
2 Cenni introduttivi 3
2.1 Introduzione a Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.2 Cos' un Framework? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

3 Spring Framework 4
3.1 Descrizione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

3.2 Propriet e Vantaggi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

3.3 Moduli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

3.3.1 Core Container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

3.3.2 Data Access/Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3.3.3 Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3.3.4 AOP, Aspect and Instrumentation . . . . . . . . . . . . . . . . . . . . . . . 6

3.3.5 Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3.4 Inversion of Control e Dependency Injection . . . . . . . . . . . . . . . . . . . . . . 7

3.5 Spring Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3.5.1 Constructor Dependency Injection . . . . . . . . . . . . . . . . . . . . . . . 9

3.5.2 Setter Dependency Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

3.5.3 Richiamo dei beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

3.6 Utilizzo delle Annotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.7 Sviluppo di un applicazione con Spring . . . . . . . . . . . . . . . . . . . . . . . . . 15

4 Integrazione di Enterprise JavaBeans 19


5 Spring MVC 20
5.1 Descrizione delle componenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

5.2 Esempio di un applicazione con Spring MVC . . . . . . . . . . . . . . . . . . . . . 22

6 Conclusioni 26
7 Bibliograa 27

1
1 Introduzione
Negli ultimi anni il continuo evolversi delle tecnologie per lo sviluppo di software, ha portato privati

e aziende a richiedere applicazioni sempre pi complesse e strutturate, solitamente dotate di un

interfaccia graca per gestire al meglio i propri dati. Questo richiede al programmatore la capacit

di doversi adattare alle diverse problematiche che si incontrano durante lo sviluppo di applicazioni;

da qui nasce l'esigenza di lavorare su piattaforme che agevolino il compito del programmatore.

In un primo momento, venne molto apprezzata la tecnologia JavaBeans, ancora in uso, che preve-

deva l`utilizzo di semplici classi java (beans) con regole determinate di nomenclatura per la loro

introspezione (propriet accessibili mediante metodi pressati da get e set); tuttavia anche questa

col tempo ha cominciato a mostrare i suoi limiti (di cui discuteremo nell'elaborato), motivo per

cui si continuata la ricerca di tecnologie sempre pi adeguate.

Ed qui che entra in scena Spring, un framework nato per supportare i programmatori nello svi-

luppo di software per componenti e integrabile con altre tecnologie(EJB compresa).

Nel seguente elaborato viene riportata una panoramica di questo framework mostrandone la strut-

tura, i punti di forza e qualche esempio che mostra come realizzare un'applicazione sia standalone

che Web.

2
2 Cenni introduttivi
2.1 Introduzione a Java

Java un linguaggio di programmazione orientato agli oggetti progettato per essere indipendente

dalla piattaforma sica di esecuzione; tale progetto venne iniziato da James Gosling ed altri inge-

gneri presso la Sun MicroSystems e ucializzato nel 1995.

I programmi scritti con questo linguaggio vengono compilati ed eseguiti su una piattaforma soft-

ware(piattaforma Java) composta da due blocchi compositivi:

1. Java Virtual Machine(JVM): provvede all'esecuzione vera e proprio del programma.


2. API Java: una collezione di componenti software (librerie) gi scritti e pronti all'uso.

Il codice sorgente Java viene dapprima compilato con un compilatore java ( javac), il quale genera
il codice compilato (detto bytecode) che verr poi passato alla JVM, la quale dispone di un

interprete che le consente di tradurre il bytecode in linguaggio macchina per poi eseguirlo.

Java si divide essenzialmente in tre piattaforme dierenti, utili a seconda dell'uso e del tipo di

progetto da sviluppare:

1. Java 2 Standard Edition (J2SE): E' la piattaforma pi utilizzata, contiene il Java

Developer Kit che serve per compilare i codici sorgenti Java.

2. Java 2 Enterprise Edition (J2EE): Una piattaforma di sviluppo interamente dedicata a


soluzioni Client - Server, utilizza un Application Server che memorizza gli oggetti, i database

ed i componenti nel server, che saranno poi utilizzati dallo sviluppatore Java Client: alcuni

esempi sono le JSP, le Servlet gli EJB.

3. Java 2 Micro Edition (J2ME): La piattaforma di sviluppo per i dispositivi portabili,

come cellulari o palmari.

2.2 Cos' un Framework?

Un framework un'architettura logica di supporto (spesso un'implementazione logica di un par-

ticolare design pattern) su cui un software pu essere progettato e realizzato, spesso facilitandone

lo sviluppo da parte del programmatore.

La sua funzione quella di creare una infrastruttura generale, lasciando al programmatore il con-

tenuto vero e proprio dell'applicazione. Lo scopo di un framework infatti quello di risparmiare

allo sviluppatore la riscrittura di codice gi scritto in precedenza per compiti simili.

Esso denito da un insieme di classi astratte e dalle relazioni tra esse. Istanziare un framework

signica fornire un'implementazione di tali classi.

Nella pratica un framework viene messo a disposizione sotto forma di archivio contenente le clas-

si software che lo sviluppatore pu utilizzare e gestire. Ovviamente questo non coincide con il

semplice mettere a disposizione delle librerie di classi in quanto quando si utilizza un framework

bisogna attenersi alle speciche denite dal framework stesso e lasciargli il usso di controllo.

I framework possono essere creati per diversi obiettivi: gestione della persistenza, realizzazione di

applicazioni Web, O/R mapping, etc...

3
3 Spring Framework
3.1 Descrizione

Spring un framework open source per lo sviluppo di applicazioni Java, in particolare per appli-

cazioni J2EE.

La prima versione del framework fu rilasciata nel 2002 da Rod Johnson, subendo poi molti cam-

biamenti che hanno portato questo framework ad essere molto apprezzato dalla comunit interna-

zionale ed a vincere nel 2006 un Jolt productivity award e un JAX Innovation Award.

Spring molto apprezzato nella comunit Java grazie degli innumerevoli vantaggi che esso ore,

come la modulart, l'integrabilit, la portabilit...di cui tratteremo a breve; per di pi tale fra-

mework rappresenta anche una valida alternativa a Enterprise JavaBean(EJB), in quanto lascia

una maggiore libert al programmatore mettendo a disposizione un'ampia gamma di soluzioni ben

documentate, semplici e adatte alle problematiche pi comuni.

Tuttavia, nonostante Spring metta a disposizione strumenti per realizzare qualsiasi tipo di applica-

zioni Java, il settore in cui pi viene utilizzato quello delle applicazioni web-based (in particolare

quelle che si basano sul modello MVC) costruite sul modello della piattaforma Java EE.

Questo ha permesso a Spring di essere riconosciuto anche da importanti vendor commerciali quale

framework di importanza strategica.

3.2 Propriet e Vantaggi

Il framework Spring gode delle seguenti propriet:

1. Modulare: Pur essendo molto ampio, grazie alla sua modularit si pu scegliere di integrare

solo alcuni dei suoi moduli all'interno del nostro progetto. Per questo Spring facilmente

integrabile anche in progetti gi esistenti.

2. Lightweight: Spring stato progettato in modo da rendere le dipendenze dal framework

all'interno della nostra business logic praticamente nulle, e ove presenti facilmente isolabili.

Per instaziare einizializzare oggetti nel framework non si devono implementare interfacce

speciche o classi astratte.

3. Integrabile: In Spring non ci sono package di logging, connection pool o O/R mapping,

poich tutte queste funzionalit sono fornite da altri framework open source. Spring non ha

l'obbiettivo di sostituirli, ma solo di renderli pi facili da utilizzare, attraverso i suoi tool.

4. Portabile: Un'applicazione scritta con Spring pu essere trasferita senza problemi da un

Application Server all'altro.

5. POJO-based programming enabled: Spring ci permette di sviluppare una completa

applicazione J2EE usanso solo POJO, dotandoli di funzionalit enterprise in modo non

invasivo.

6. Test driven enabled: Spring ci permette di scrivere software facile da testare, quindi risulta

un framework ideale per i software che sono scritti basandosi sul Test Driven Development.

4
Inoltre ore anche i seguenti vantaggi:

Elimina la proliferazione di custom properties le. Per capire quali sono le dipendenze di una

classe, basta solo guardarne il costruttore o le sue property. Questo possibile grazie all'uso

dell' Inversion of Control e del Dependency Injection;

Ci aiutia a risolvere i problemi comuni delle applicazioni enterprise, rendendo opzionale l'uso

degli EJB. In questo modo possiamo scegliere di implemenrare le interfacce di business nei

nostri POJOs o nei nostri EJB senza modicare il codice chiamante;

Ore un consistente framework per il Data Access, sia usando JDBC, sia usando altri prodotti

di O/R mapping, come Hibernate o TopLink.

3.3 Moduli

Come accennato nel precedente paragrafo, Spring un framework modulare. Le sue funzionalit

sono distribuite all'interno di circa 20 moduli, alcuni dei quali sono raggruppati all'interno di

Container, come in gura seguente:

Figura 1: Moduli Spring

3.3.1 Core Container


I moduli Core e Beans costituiscono la parte fondamentale del framework, includendo le funziona-
lit di Inversion of Control e Dependency Injection che sono implementate tramite la BeanFactory

che una sosticata implementazione del Factory Method Pattern.

Esso consente il disaccoppiamento tra denizione e congurazione delle dipendenze e della logica

applicativa.

Il modulo Context costituisce il mezzo di accesso agli oggetti attraverso la sua interfaccia Applica-
tionContext. L'ApplicationContext eredita tutti le funzionalit della BeanFactory, aggiungendone

altre quali: supporto per l'internazionalizzazione, propagazione di eventi, caricamento di risorse, il

supporto per J2EE.

5
Il modulo Expression Language fornisce una potente espressione di linguaggio per la ricerca

e la manipolazione degli oggetti a runtime. Tale linguaggio supporta le operazioni di modica e re-

stituzione dei valori(setvalue e getvalue),operazioni di assegnamento, invocazione di metodi, utilizzo

di operatori logici e aritmetici, denizione di variabili, l'elencazione di una lista e l'aggregazione

tra pi liste.

3.3.2 Data Access/Integration


Il modulo JDBC fornisce un'astrazione delle API JBDC, eliminando la necessit di codicare e
analizzare il codice dei dierenti database-vendor.

Il modulo ORM fornisce un livello di integrazione con le API di Object-Relational(O/R) mapping


come JPA, IDO, Hibernate e iRatis. Usando il package ORM possibile combinare le potenzialit

di questi framework con le peculiarit oerte da Spring, come la gestione delle transazioni.

Il modulo OXM fornisce un livello di astrazione che supporta le implementazione del mapping

Object/XML per JAXB, Castor, XMLBeans, JiBX and XStream.

Il modulo JMS contiene le funzionalit per la produzione e consumazione dei messaggi.

3.3.3 Web
Il modulo Web contiene le funzionalit di base per creare applicationi enterprise, come ad esempio
il supporto per l'upload dei le, orendo anche l'inizializzazione del container IoC attraverso un

Servlet Listener.

Il modulo Servlet contiene l'implementazione del Model-View-Controller(MVC) di Spring per

le applicazioni web. Il framework MVC di Spring provvede a una netta separazione del dominio

del codice del Model da quello della View ; per di pi si integra con tutte le altre caratteristiche di
Spring Framework.

Il modulo Portlet fornisce funzionalit identiche al modulo Web-Servlet, ma orientato ad ap-

plicazioni che fanno uso di portlet.

Il modulo Struts contiene classi per l'integrazione con Struts2, che per sconsiglita nella versione
3 di Spring.

3.3.4 AOP, Aspect and Instrumentation


Il modulo AOP fornisce un'implementazione aderente alla AOP Alliance, permettendo una pro-

grammazione aspect-oriented. Questo layer consente di creare codice che deve essere disaccoppiato

dalle altre funzionalit, anche se legato al usso generale dell'applicativo.

Questo layer ha anche un modulo Aspects per l'integrazione con AspectJ, ed un modulo Instru-

mention che consente il monitoraggio delle classi.

3.3.5 Test
Il modulo Test ore la possibilt di testare i componenti di Spring, usando JUnit o TestNG.

6
3.4 Inversion of Control e Dependency Injection

Nella programmazione orientata agli oggetti uno degli obiettivi principali che ci si impone quello

di realizzare applicazioni che siano quanto pi possibili modulari e fare sicch tra i vari moduli che

costituiscono un'applicazione vi sia un basso grado di accoppiamento (cio siano quanto pi possi-

bile indipendenti gli uni dagli altri); in tal modo infatti si garantisce la riusabilit e la testabilit

dei vari moduli.

Tuttavia quando si realizzano applicazioni molto complesse, inevitabile che si instaurino delle

dipendenze tra vari i vari oggetti (si pensi all'ereditariet e alla composizione tra le classi).

Il framework Spring perci propone una strategia per eliminare queste dipendenze tra classi, ovvero

l'Inversione del Controllo, e questa funzionalit rappresenta un' altro dei suoi punti forti.

L'Inversione del Controllo (in inglese Inversion of Control, abbreviato in IoC) un pattern

per cui un componente di livello applicativo riceve il controllo da un componente appartenente a

un libreria riusabile; in parole povere, sposta la denizione delle dipendenze tra gli oggetti, dal

codice (scritto dallo sviluppatore) al framework. Spring realizza l'IoC tramite la tecnica della De-
pendency Injection che di base consiste nell'avere un oggetto separato(un le .xml) che si occupi
della risoluzione delle dipendenze e della loro inizializzazione.

Normalmente, senza l'utilizzo di questa tecnica, se un oggetto necessita di accedere ad un partico-

lare servizio, l'oggetto stesso si prende la responsabilit di gestirlo, o avendo un diretto riferimento

al servizio, o individuandolo con un Service Locator che gli restituisce un riferimento ad una spe-

cica implementazione del servizio. Con l'utilizzo della dependency injection, l'oggetto ha in s

solamente una propriet che pu ospitare un riferimento a quel servizio e, quando l'oggetto viene

istanziato, un riferimento ad una implementazione di questo servizio gli viene iniettata dal fra-

mework esterno, senza che il programmatore che crea l'oggetto sappia nulla sul posizionamento del

servizio o altri dettagli dello stesso.

Vediamo un esempio di dipendenza:

Agenda.java

1 package agenda ;
2
3 import java . util . ArrayList ;
4 import utente . Utente ;
5
6 public class Agenda implements IAgenda
7 {
8 private ArrayList < Utente > users ;
9
10 public Agenda ()
11 { users = new ArrayList < >();}
12
13 public void printAll ()
14 {
15 for ( int i =0; i < users . size (); i ++)
16 users . get (i ). print ();
17 }
18
19 public ArrayList < Utente > getAgenda ()
20 { return users ;}

7
21
22 public void setAgenda ( ArrayList < Utente > agenda )
23 { this . users = agenda ;}
24
25 public void addUser ( String nome , String cognome , int eta )
26 { users . add ( new Utente ( nome , cognome , eta ));}
27 }

Inne la classe di servizio Gestore istanzia al suo interno un vettore di Utenti e ne invoca il servizio

esposto

Gestore.java

1 public class Gestore


2 {
3 private Agenda agenda ;
4
5 public Gestore ()
6 {
7 // Configurazione e risoluzione dipendenze
8 agenda = new Agenda ();
9 }
10
11 public void addUser ( String nome , String cognome , int eta )
12 { agenda . addUser ( nome , cognome , eta );}
13
14 public void printUsersMaggiorenni ()
15 {
16 ArrayList < Utente > lista = agenda . getAgenda ();
17 for ( int i =0; i < lista . size (); i ++)
18 if ( lista . get (i ). getEta () >=18)
19 System . out . println ( lista . get (i ). getNome ());
20 }
21 }

Utilizzando invece la tecnica del Dependency Injection la dipendenza dall'oggetto Agenda viene

risolta all'interno del framework Spring, evitando di risolvere la stessa nel costruttore della classe

Gestore.

Ci sono come vedremo 3 tipi di Dependency Injection:

1. Constructor Injection;

2. Setter Injection;

3. Interface Injection.

Spring tuttavia implementa solo le prime due.

8
3.5 Spring Beans

In questa sezione vedremo come congurare un IoC Container attraverso i metadati xml.

Per istanziare un bean ci occorrono due informazioni:

un id per identicare il bean(generalmente una stringa);


Qualied Name della classe a cui appartiene l'oggetto.
ad esempio:

1 < bean id =" utente1 " class =" com . Utente " >
2 </ bean >

E' possibile poi includere un terzo parametro cio la visibilit del bean(scope) che ne stabilisce il

ciclo di vita; Spring ammette 5 tipi di scope e sono:

singleton : viene creata una sola istanza a livello di container;

prototype : una nuova istanza creata ogni volta che richiesta;

request : viene creata una sola istanza per le richieste HTTP;

session : viene creata una sola istanza per le sessioni HTTP;

globalsession : viene creata una sola istanza per l'intera sessione HTTP;

Se l'attributo non specicato viene settato singleton di default.

ad esempio:

1 < bean id =" utente1 " class =" com . Utente " scope =" singleton " >
2 </ bean >

I beans possono essere istanziati attraverso 3 metodi diversi:

Attraverso il costruttore;

Attraverso un factory method;

Attraverso un factory bean.

Se non specicato un metodo, Spring di default utilizza un costruttore per istanziare i bean,

quindi ogni bean deve avere il costruttore di default.

Vediamo ora come realizzare l'IoC attraverso la Setter Dependency Injection e la Constructor

Setter Dependency.

3.5.1 Constructor Dependency Injection


In questo caso modo le dipendenze tra due oggetti vengono risolte attraverso il costruttore del

bean che vuole utilizzare un certo servizio di un'altro bean. Per chiarire riportiamo un esempio.

Supponiamo di avere la seguente classe:

1 public class BeanA


2 {
3 private beanName ;
4 private BeanB beanB ;
5

9
6 public BeanA ( String beanName , BeanB beanB )
7 {
8 this . beanName = beanName ;
9 this . beanB = beanB ;
10 }
11
12 // ... business logic
13
14 }

La classe BeanA ha una dipendenza da quella BeanB. Vediamo come congurarla nel le .xml:

1 // Istanziamo un oggetto BeanB


2 < bean id =" bean_B " class =" com . BeanB " scope =" singleton " >
3 </ bean >
4
5 < bean id =" bean_A " class =" com . BeanA " scope =" prototype " >
6 < constructor - arg value = " nome_del_bean " index ="0"/ >
7 < constructor - arg ref =" bean_B " index ="1 "/ >
8 </ bean >

Quindi per congurare la dipendenza tramite costruttore si utilizza il tag constructor-arg insieme

agli attributi:

value per passare valori predeniti come stringhe e numeri

ref per passare come argomento un altro bean gia istanziato nell'IoC Container.

L'attributo index serve per specicare l'ordine con cui passare i parametri al costruttore. Non

necessario quando i tipi degli argomenti da passare sono tutti diversi tra loro.

3.5.2 Setter Dependency Injection


La Constuctor Dependency Injection non adatta per per risolvere dipendenze cicliche tra due

oggetti(A dipende da B e viceversa), compito che invece puo essere svolto dalla Setter Dependency

Injection.

Tale tecnica permette di iniettare le dipendenze dopo che l'oggetto stato istanziato; solo neces-

sario denire i metodi Getter e Setter all'interno della classe che ha la dipendenza.

Cio riprendendo l'esempio del paragrafo precedente(BeanA che dipende da BeanB) avremo:

1 public class BeanA


2 {
3 private beanName ;
4 private BeanB beanB ;
5
6 public BeanA ( String beanName , BeanB beanB )
7 {
8 this . beanName = beanName ;
9 this . beanB = beanB ;
10 }
11
12 public void setBeanB ( BeanB beanB )
13 { this . beanB = beanB ;}
14

10
15 public BeanB getBeanB ()
16 { return this . beanB ;}
17
18 // ... business logic
19
20 }

e la dipendenza sar risolta cos:

1 // Istanziamo un oggetto BeanB


2 < bean id =" bean_B " class =" com . BeanB " scope =" singleton " >
3 </ bean >
4
5 < bean id =" bean_A " class =" com . BeanA " scope =" prototype " >
6 < property name =" beanB " ref = " bean_B " / >
7 </ bean >

E' anche possibile iniettare degli oggetti con dei valori statici e rappresentazione in string.

Ad esempio se abbiamo la seguente classe:

1 public class Utente


2 {
3 private String nome ;
4 private String cognome ;
5 private int eta ;
6
7 public Utente ( String nome , String cognome , int eta )
8 {
9 this . nome = nome ;
10 this . cognome = cognome ;
11 this . eta = eta ;
12 }
13
14 // ... e relativi metodi Setters e Getters per ogni attributo
15 }

Allora possibile istanziare un bean Utente nel seguente modo:

1 < bean id =" utente1 " class =" com . Utente " >
2 < property name =" nome " value =" Pasquale " / >
3 < property name =" cognome " value =" Tremante "/ >
4 < property name =" eta " value =25/ >
5 </ bean >

11
3.5.3 Richiamo dei beans
Supponiamo di aver istanziato un beanA e un beanB all'interno di un le 'beans.xml', vediamo ora
come richiamarli all'interno di un programma principale:

1 public class Main


2 {
3 public static void main ( String [] args )
4 {
5 // Istanzio IoC Container
6 ApplicationContext context = new ClassPathXmlApplicationContext (" beans . xml " );
7 // Recupero del beanB
8 BeanB beanB =( BeanB ) context . getBean (" bean_B " );
9 // Recupero del beanA
10 BeanA beanA =( BeanA ) context . getBean (" bean_A " );
11
12 // ... utilizzo dei beans
13
14 }
15 }

L'ApplicationContext un container pi avanzato rispetto alla BeanFactory. Estende la BeanFac-

tory e fornisce altre funzionalit. Ci sono diverse implementazioni dell'ApplicationContext che si

possono utilizzare tra le quali:

ClassPathXmlApplicationContext : permette di caricare l'ApplicationContext da un le xml

presente nel classpath dell'applicazione;

FileSystemXmlApplicationContext : permette di caricare l'ApplicationContext da un le xml

presente nel le system (occorre specicare un percorso assoluto)

12
3.6 Utilizzo delle Annotations

Finora abbiamo visto come congurare le dipendenze tra i bean attraverso metadati in formato

xml, tuttavia Spring ore anche la possibilit di farlo tramite le Annotations.


Ad esempio viene fornita l'annotation @Autowired la quale pu essere usata per congurare

l'iniezione di dipendenza attraverso un metodo setter,un campo o il costruttore di una classe.

Vediamo come...

Supponiamo di avere la seguente classe:

1 public class AutowiredBean


2 {
3 private BeanA beanA ;
4 private BeanB beanB ;
5
6 @Autowired
7 public AutowiredBean ( BeanA beanA , BeanB beanB )
8 {
9 this . beanA = beanA ;
10 this . beanB = beanB ;
11 }
12
13 // business logic ..........
14 }

In tal caso @Autowired stata utilizzata sul costruttore della classe, quindi il le di congurazione

xml avr quindi la seguente forma:

1 < context : annotation - config />


2
3 < bean id =" bean_A " class =" com . BeanA "/>
4 < bean id =" bean_B " class =" com . BeanB "/>
5
6 < bean id =" autowiredBean " class =" com . AutowiredBean "/>

Da notare che di default la congurazione attraverso le Java Annotation non abilitata, per abi-

litarla necessario inserire nel le xml il tag <context:annotation-cong/>.


Nel caso invece volessimo iniettare la dipendenza attraverso un metodo setter o un campo, imple-

mentiamo la classe precedente come segue:

1 public class AutowiredBean


2 {
3 @Autowired // iniezione attraverso un campo
4 private BeanA beanA ;
5
6 private BeanB beanB ;
7
8 public BeanA getBeanA ()
9 { return this . beanA ;}
10
11 public BeanB getBeanB ()
12 { return this . beanB ;}
13
14 public void setBeanA ( BeanA beanA )
15 { this . beanA = beanA ;}
16
17 @Autowired // iniezione attraverso un metodo setter

13
18 public void setBeanB ( BeanB beanB )
19 { this . beanB = beanB ;}
20
21 // business logic ..........
22 }

e il le xml resta identico a quello precedente.

Un'altra annotation utile @Qualier che serve per specicare l'id del bean che si vuole iniettare,
nel caso ce ne siano due della stessa classe. Ad esempio:

1 public class AutowiredBean


2 {
3 @Autowired
4 @Qualifier ( " bean_1 ")
5 private BeanA beanA ;
6
7 private BeanB beanB ;
8
9 // Metodi Setter e Getter
10
11 // business logic ....
12 }

oppure:

1 public class AutowiredBean


2 {
3 private BeanA beanA ;
4 private BeanB beanB ;
5
6 @Autowired
7 public AutowiredBean ( @Qualifier (" bean_1 " ) BeanA beanA , BeanB beanB )
8 {
9 this . beanA = beanA ;
10 this . beanB = beanB ;
11 }
12 }

cos, nel caso avessimo un le xml come il seguente:

1 < context : annotation - config / >


2
3 < bean id =" bean_1 " class =" com . BeanA "/ >
4 < bean id =" bean_2 " class =" com . BeanA "/ >
5 < bean id =" bean_B " class =" com . BeanB "/ >
6
7 < bean id =" autowiredBean " class =" com . AutowiredBean "/ >

solo il bean_1 sar iniettato all'interno del bean autowiredBean.

14
3.7 Sviluppo di un applicazione con Spring

Sviluppiamo ora un'applicazione in Spring che riassuma e mostri le funzionalit discusse no ad

ora.

Riportiamo innanzitutto l'implementazione dell'interfaccia e della classe Utente:

IUtente.java

1 package com . utente ;


2
3 public interface IUtente
4 {
5 public String getNome ();
6 public void setNome ( String nome );
7 public String getCognome ();
8 public void setCognome ( String cognome );
9 public int getEta ();
10 public void setEta ( int eta );
11 }

Utente.java

1 package com . utente ;


2
3 public class Utente implements IUtente
4 {
5 private String nome ;
6 private String cognome ;
7 private int eta ;
8
9 public Utente ( String nome , String cognome , int eta )
10 {
11 this . nome = nome ;
12 this . cognome = cognome ;
13 this . eta = eta ;
14 }
15
16 public String getNome ()
17 { return nome ;}
18
19 public void setNome ( String nome )
20 { this . nome = nome ;}
21
22 public String getCognome ()
23 { return cognome ;}
24
25 public void setCognome ( String cognome )
26 { this . cognome = cognome ;}
27
28 public int getEta ()
29 { return eta ;}
30
31 public void setEta ( int eta )
32 { this . eta = eta ;}
33 }

15
Riportiamo l'implementazione dell'interfaccia e della classe Agenda:

IAgenda.java

1 package com . agenda ;


2
3 import java . util . ArrayList ;
4 import com . utente . Utente ;
5
6 public interface IAgenda
7 {
8 public void setAgenda ( ArrayList < Utente > agenda );
9 public ArrayList < Utente > getAgenda ();
10 public void addUser ( String nome , String cognome , int eta );
11 }

Agenda.java

1 package com . agenda ;


2
3 import java . util . ArrayList ;
4 import com . utente . Utente ;
5
6 public class Agenda implements IAgenda
7 {
8 private ArrayList < Utente > users ;
9
10 public Agenda ()
11 { users = new ArrayList < >();}
12
13 public ArrayList < Utente > getAgenda ()
14 { return users ;}
15
16 public void setAgenda ( ArrayList < Utente > agenda )
17 { this . users = agenda ;}
18
19 public void addUser ( String nome , String cognome , int eta )
20 { users . add ( new Utente ( nome , cognome , eta ));}
21 }

16
Riportiamo l'implementazione della classe Gestore:

Gestore.java

1 package com . service ;


2
3 import java . util . ArrayList ;
4 import org . springframework . context . ApplicationContext ;
5 import org . springframework . context . support . ClassPathXmlApplicationContext ;
6 import com . agenda . Agenda ;
7 import com . agenda . IAgenda ;
8 import com . utente . Utente ;
9
10 public class Gestore
11 {
12 private IAgenda agenda ;
13
14 public Gestore ()
15 { super ();} // Non ci sono risoluzioni di dipendenze nel costr .
16
17 // Metodi Getter and Setter necessari realizzare la Dep . Injection
18 public IAgenda getAgenda ()
19 { return agenda ;}
20
21 public void setAgenda ( IAgenda agenda )
22 { this . agenda = agenda ;}
23
24 public void printUsersMaggiorenni ()
25 {
26 ArrayList < Utente > lista = agenda . getAgenda ();
27 for ( int i =0; i < lista . size (); i ++)
28 if ( lista . get (i ). getEta () >=18)
29 System . out . println ( lista . get (i ). getNome ());
30 }
31
32 public void printAllUsers ()
33 {
34 ArrayList < Utente > lista = agenda . getAgenda ();
35 for ( int i =0; i < lista . size (); i ++)
36 System . out . println ( lista . get (i ). getNome ());
37 }
38
39 public static void main ( String [] args )
40 {
41 // Riportato in seguito per commentarlo meglio ...
42 }
43 }

Da notare che nel costruttore della classe Gestore non stata risolta la dipendenza con la classe

Agenda; questa verr risolta nel le di congurazione 'Beans.xml' tramite la Setter Dependency

Injection(infatti abbiamo aggiunto alla classe Gestore anche i metodi setAgenda e getAgenda).

Riportiamo quindi anche il le di congurazione 'Beans.xml' :

17
Beans.xml

1 <? xml version ="1.0" encoding =" UTF -8" ? >


2 < beans
3 // Righe necessarie per la configurazione di Spring
4 xmlns =" http :// www . springframework . org / schema / beans "
5 xmlns : xsi =" http :// www . w3 . org /2001/ XMLSchema - instance "
6 xsi : schemaLocation =" http :// www . springframework . org / schema / beans
7 http :// www . springframework . org / schema / beans / spring - beans . xsd " >
8
9 // Definizione del bean di tipo Agenda
10 < bean id =" agnd " class = " com . agenda . Agenda " scope = " singleton " >
11 </ bean >
12
13 // Definizione del bean di tipo Gestore con uso della Setter Injection
14 < bean id =" gest " class = " com . service . Gestore " scope =" prototype " >
15 < property name =" agenda " ref =" agnd " ></ property >
16 </ bean >
17
18 </ beans >

Riportiamo inne il programma principale(denito come metodo della classe Gestore) per vedere

come i bean vengono richiamati e utilizzati:

Gestore.java

1 package com . service ;


2
3 import java . util . ArrayList ;
4 import org . springframework . context . ApplicationContext ;
5 import org . springframework . context . support . ClassPathXmlApplicationContext ;
6 import com . agenda . Agenda ;
7 import com . agenda . IAgenda ;
8 import com . utente . Utente ;
9
10 public class Gestore
11 {
12 ... // business logic g i definita prima
13 public static void main ( String [] args )
14 {
15 // Recupero del file Beans . xml dal classpath
16 ApplicationContext context = new ClassPathXmlApplicationContext (" Beans . xml " );
17 // Recupero e utilizzo del bean agnd
18 Agenda agnd =( Agenda ) context . getBean (" agnd " );
19 agnd . addUser ( " Pasquale " ," Tremante " ,25);
20 agnd . addUser ( " Emanuele " ," Tremante " ,9);
21 agnd . addUser ( " Miky " ," Cuomo " ,27);
22 agnd . addUser ( " Lucia " ," Oione " ,26);
23 agnd . addUser ( " Francesco " ," Bonifacio " ,15);
24 agnd . addUser ( " Antonio " ," Miccio " ,18);
25 // Recupero e utilizzo del bean Gestore
26 Gestore gest =( Gestore ) context . getBean (" gest " );
27 gest . printAllUsers ();
28 System . out . println ();
29 gest . printUsersMaggiorenni ();
30 }
31 }

18
4 Integrazione di Enterprise JavaBeans
Spring viene spesso considerato una valida alternativa a Enterprise JavaBeans,questo perch quasi

la maggior parte delle applicazioni realizzate combinando le funzionalit di Spring con quelle di

accesso ORM e JBDC, si sono rivelate una scelta migliore rispetto a quelle realizzate con i container

EJB e relativi EJBs.

Tuttavia importante precisare che l'utilizzo di Spring non previene l'utilizzo degli EJBs, bens ne

rende pi semplice l'accesso e l'implementazione delle loro funzionalit.

Per di pi, usando Spring, l'accesso ai servizi forniti dagli EJBs permette l'implementazione di

quei servizi che rendono trasparente il passaggio da EJB locali a remoti, senza che il codice Client

debba essere modicato, ma vediamo ora qualcosa pi nel dettaglio.

Ricordiamo che, utilizzando EJB, per invocare un metodo su un session bean stateless(locale o

remoto), il codice cliente deve innanzitutto eettuare un'operazione di JNDI lookup per ottenere

un oggetto EJB-Home tramite il quale otterr l'oggetto vero e proprio,cio EJB-Object, sul quale

potr invocare i metodi desiderati.

Quindi per ridurre la quantit di codice, molte applicazioni EJB utilizzano i pattern Service

Locator e Business Delegate, i quali costituiscono un'alternativa migliore alle operazioni di JNDI

lookup; tuttavia presentano i seguenti svantaggi:

Solitamente il codice che utilizza gli EJBs dipende dai Service Locator e Business Delegate

singletons, rendendo dicile il testing del codice;

Nel caso venga utilizzato il pattern Service Locator senza quello Business Delegate, il

codice dell'applicazione nisce con il dover richiamare il metodo create() su un EJB home, e

arontare le eccezioni derivanti. Di conseguenza, rimane legata all'API EJB la complessit

di programmare il modello EJB;

L'implementazione del pattern Business Delegate consiste nella duplicazione di codice, in

cui bisogna scrivere numerosi metodi che semplicemente richiamano gli stessi metodi dell'

EJB.

L'approccio Spring permette la creazione e l'utilizzo di oggetti proxy, normalmente congurati

all'interno di un container Spring, i quali operano come delegati del codice; quindi non necessario

scrivere un altro Service Locator, eettuare un altro JNDI lookup o duplicare metodi nel Business

Delegate.

19
5 Spring MVC
Spring MVC la parte del framework che fornisce le funzionalit per la realizzazione di applicazioni

WEB basate sul pattern Model-View-Control(MVC), orendo sempre la possibilit di sfruttare i

punti di forza di Spring come l'inversion of control (tramite dependency injection) e la aspect

oriented programming.

Spring MVC implementa perfettamente il pattern mantenendone sia i concetti che la nomenclatura.

All'interno di una applicazione Spring MVC troviamo infatti:

i Model che sono rappresentati dalle classi che a loro volta rappresentano gli oggetti gestiti
e le classi di accesso al database;

le View che sono rappresentate dai vari le JSP (compilati in HTML) e da eventuali classi
per l'esportazione in formati diversi da HTML (PDF, XLS, CSV. . . );

i Controller sono rappresentati da classi (chiamate appositamante Controller) che rimango-


no in ascolto su un determinato URL e, grazie ai Model e alle View, si occupano di gestire

la richiesta dell'utente.

5.1 Descrizione delle componenti

Per implementare il pattern MVC, Spring usa tre elementi principali:

DispatcherServlet
View Resolver
Handlers
La DispatcherServlet una servlet(oggetto scritto in linguaggio Java che opera all'interno di

un server web) che si occupa di smistare tutte le richieste (POST,GET,PUT ...) ai vari handlers,

quindi funge da Front Controller.

La DispatcherServlet, essendo una servlet, deve essere mappata nel le web.xml nel seguente modo:

web.xml

1 < servlet >


2 < servlet - name > dispatcher </ servlet - name >
3 < servlet - class > org . springframework . web . servlet . DispatcherServlet </ servlet - class >
4 <load -on - startup >1 </ load -on - startup >
5 </ servlet >
6
7 < servlet - mapping >
8 < servlet - name > dispatcher </ servlet - name >
9 <url - pattern >/ example /* </ url - pattern >
10 </ servlet - mapping >

La servlet dispone di un proprio WebApplicationContext che estende quello principale, aggiungen-

do tutti i beans dichiarati nel le WEB-INF/dispatcher-servlet.xml. In particolare tra questi beans

ci saranno gli handlers delle richieste e i View Resolver.

Gli handlers (detti anche controller) sono i beans che si occupano di servire realmente le richieste
fornite dalla DispatcherServlet, e sono quindi quelli che implementano la business logic dell'appli-

cazione.

Vediamo un esempio di implementazione di un controller:

20
controller.java

1 @Controller
2 public class MyController {
3 @RequestMapping ( value = "/" , method = RequestMethod . GET )
4 public String paginaPersonale ( Model model ) {
5 model . addAttribute (" nome " , " Pasquale " );
6 model . addAttribute (" cognome " , " Tremante " );
7 return " pagina - personale ";
8 }
9 }

Anche qui si pu notare l'utilizzo di annotations (sempre oerte da Spring).

@Controller serve per identicare la classe come controller;


@RequestMapping serve per evidenziare il metodo e il path (tramite l'attributo value ) per
il quale deve essere invocato tale metodo. In pi si pu denire l'HTTP method per il quale

eseguire la richiesta (POST, GET) attraverso l'attributo method.

I controller devono poi essere deniti nel le WEB-INF/dispatcher-servlet.xml ; per farlo deniamo
all'interno del le uno scanner che si occupa di trovare le classi annotate con l' annotation di Spring

e Spring MVC.

dispatcher-servlet.xml

1 <! -- Configurazione utilizzo annotation -- >


2 < mvc : annotation - driven / >
3
4 <! -- Definizone dello scanner -- >
5 < context : component - scan base - package =" com . prova . HelloMVC " / >

Attraverso questa congurazione di esempio viene detto a Spring che il mapping dei controllers av-

viene attraverso le annotation, quindi, quando viene fatta una richiesta del tipo http://..../example/

la DispatcherServlet reindirizza la chiamata al nostro controller di esempio, che eettua delle ope-

razioni sul model e poi restituisce una stringa che rappresenta il view resolver.

Il View Resolver un InternalResourceViewResolver che attraverso la stringa restituita dal

controller reindirizza ad una jsp. Per congurarlo aggiungiamo al le dispatcher-servlet.xml :

dispatcher-servlet.xml

1 < bean id =" viewResolver " class =" org . springframework . web . servlet . view .
2 InternalResourceViewResolver " >
3 < property name =" viewClass " value =" org . springframework . web . servlet . view . JstlView "/ >
4 < property name =" prefix " value ="/ WEB - INF / jsp /"/ >
5 < property name =" suffix " value =". jsp "/ >
6 </ bean >

Nel nostro esempio la jsp /WEB-INF/jsp/pagina-personale.jsp.

21
Riportiamo uno schema riassuntivo del funzionamento delle tre componenti appena illustrate:

Figura 2: Spring MVC

5.2 Esempio di un applicazione con Spring MVC

Riportiamo ora un semplice esempio che mostri come realizzare una semplice applicazione Hello-

World, utilizzando le funzionalit di Spring MVC precedentemente illustrate.

Il primo passo quello di creare il le web.xml all'interno del quale va congurato il WebApplica-

tionContext e mappata la DispatcherServlet.

web.xml

1 <? xml version ="1.0" encoding =" UTF -8" ? >


2 <web - app version = " 2.5 " xmlns =" http :// java . sun . com / xml / ns / javaee "
3 xmlns : xsi =" http :// www . w3 . org /2001/ XMLSchema - instance "
4 xsi : schemaLocation =" http :// java . sun . com / xml / ns / javaee http :// java . sun . com
5 / xml / ns / javaee / web - app_2_5 . xsd " >
6 <! -- The definition of the Root Spring Container -- >
7 < context - param >
8 < param - name > contextConfigLocation </ param - name >
9 < param - value >/ WEB - INF / spring / root - context . xml </ param - value >
10 </ context - param >
11
12 <! -- Creates the Spring Container shared by all Servlets and Filters -- >
13 < listener >
14 < listener - class >
15 org . springframework . web . context . ContextLoaderListener
16 </ listener - class >
17 </ listener >
18
19 <! -- Processes application requests -- >
20 < servlet >
21 < servlet - name > appServlet </ servlet - name >
22 < servlet - class >
23 org . springframework . web . servlet . DispatcherServlet
24 </ servlet - class >

22
25 <init - param >
26 < param - name > contextConfigLocation </ param - name >
27 < param - value >
28 / WEB - INF / spring / appServlet / servlet - context . xml
29 </ param - value >
30 </ init - param >
31 <load -on - startup >1 </ load -on - startup >
32 </ servlet >
33
34 < servlet - mapping >
35 < servlet - name > appServlet </ servlet - name >
36 <url - pattern >/ </ url - pattern >
37 </ servlet - mapping >
38 </ web - app >

Il passo seguente quello di implementare il controller:

HomeController.java

1 package com . prova . hello ;


2
3 import java . util . Locale ;
4 import org . springframework . stereotype . Controller ;
5 import org . springframework . ui . Model ;
6 import org . springframework . web . bind . annotation . RequestMapping ;
7 import org . springframework . web . bind . annotation . RequestMethod ;
8
9 @Controller
10 public class HomeController
11 {
12 @RequestMapping ( value = "/ " , method = RequestMethod . GET )
13 public String home ( Locale locale , Model model )
14 {
15 /* Aggiungiamo gli attributi nome , cognome e matricola al model
16 e ne settiamo i valori . Tali attributi verranno poi utilizzati
17 nella pagine jsp per visualizzarne i valori */
18 model . addAttribute (" nome " ," Pasquale " );
19 model . addAttribute (" cognome " ," Tremante " );
20 model . addAttribute (" matricola " ," N46001295 " );
21 /* Restituisce una stringa che corrisponde al nome della pagina
22 jsp a cui il model reindirizzera ' */
23 return " home " ;
24 }
25 }

Implementiamo poi la pagina jsp che avr il compito di mostrare i dati contenuti nel model.

Ricordiamo che jsp(Java Server Page) un linguaggio che permette di scrivere pagine che hanno

sia codice HTML sia codice Java che verr eseguito dal Server su cui si trover la pagina.

23
home.jsp

1 <%@ taglib uri =" http :// java . sun . com / jsp / jstl / core " prefix ="c" %>
2 <%@ page session =" false " %>
3 <html >
4 <head >
5 < title > Home </ title >
6 </ head >
7 <body >
8 <h1 >
9 Hello world !
10 </h1 >
11
12 <P > Io sono ${ nome } ${ cognome } e il mio numero di matricola : $ { matricola } </P >
13 </ body >
14 </ html >

Per nire implementiamo il le servlet-context.xml :

servlet-context.xml

1 <? xml version ="1.0" encoding =" UTF -8" ? >


2 < beans : beans xmlns =" http :// www . springframework . org / schema / mvc "
3 xmlns : xsi =" http :// www . w3 . org /2001/ XMLSchema - instance "
4 xmlns : beans =" http :// www . springframework . org / schema / beans "
5 xmlns : context =" http :// www . springframework . org / schema / context "
6 xsi : schemaLocation =" http :// www . springframework . org / schema / mvc
7 http :// www . springframework . org / schema / mvc / spring - mvc . xsd
8 http :// www . springframework . org / schema / beans
9 http :// www . springframework . org / schema / beans / spring - beans . xsd
10 http :// www . springframework . org / schema / context
11 http :// www . springframework . org / schema / context / spring - context . xsd " >
12
13 <!-- Abilita l ' utilizzo delle notazioni Spring -- >
14 < annotation - driven / >
15
16 <!-- Si utilizza quando si vogliono inserire delle risorse come immagini , ecc -- >
17 < resources mapping ="/ resources /** " location ="/ resources /" / >
18
19 <!-- Permette al @Controller di reindirizzare a pagine jsp -- >
20 < beans : bean class =" org . springframework . web . servlet . view .
21 InternalResourceViewResolver " >
22 < beans : property name =" prefix " value ="/ WEB - INF / views /" / >
23 < beans : property name =" suffix " value =". jsp " / >
24 </ beans : bean >
25
26 <!-- Definisce uno scanner per la ricerca delle classi @Controller
27 all ' interno del package ' com . prova . hello ' -- >
28 < context : component - scan base - package =" com . prova . hello " / >
29
30 </ beans : beans >

24
Il risultato ottenuto sar il seguente:

Per lo sviluppo dell'applicazione abbiamo utilizzato SpringToolSuite, una variante di Eclipse rea-

lizzata appositamante per utilizzare le funzionalit di Spring e scaricabile direttamente dal sito

uciale di Spring.

L'applicazione fornisce svariate agevolazioni tra cui quella di generare automaticamente i le di

congurazione servlet-context.xml e web.xml.

25
6 Conclusioni
Si conclude qui il nostro tour su Spring. In realt ci sarebbero ancora tantissimi altri aspetti im-

portanti da trattare, altrettante funzionalit da mostrare e ovviamente anche gli esempi mostrati

non riescono ad evidenziare al meglio tutti i vantaggi che il framework ore, anche perch i beneci

veri e propri cominciano a farsi sentire nella realizzazione di applicazioni su larga scala. Tuttavia,

nonostante il percorso sia stato molto breve, esso stato comunque intenso. Abbiamo infatti visto

come grazie all'Inversion of Control e alla Dependency Injection si possano implementare classi di

oggetti, minimizzando le dipendenze che vi sono semplicemente scrivendo poche righe di xml. Ab-

biamo poi visto come Spring si sia rivelato un'ottima alternativa a Enterprise JavaBean, non solo

perch lo integra al proprio interno ma anche perch ne rende pi semplice e funzionale l'utilizzo.

Inne abbiamo visto come Spring implementi in modo facile ed eciente il pattern MVC mante-

nendo i vantaggi illustrati prima, capendo quindi come mai il framework sia molto apprezzato da

molti vendor commerciali.

Insomma il framework Spring rappresenta al momento il tentativo pi riuscito per semplicare lo

sviluppo di applicazioni enterprise di una certa complessit nell`ambito Java. Esso interpreta

ottimamente i concetti dell`IoC e dall`AOP che gli permettono di raggiungere un livello di disac-

coppiamento tra le componenti software che non era mai stato raggiunto della tecnologia EJB. In

pi ore una vasta gamma di soluzioni per coprire i problemi pi comuni che si incontrano nello

sviluppo del software.

26
7 Bibliograa
1. Spring Framework: Reference Documentation,
http://docs.spring.io/spring-framework/docs/3.0.x/reference/index.html

2. Mr.Webmaster: Guida Java Spring,


http://www.mrwebmaster.it/java/guide/guida-spring/

3. HTML.it: Guida Spring MVC,


http://www.html.it/guide/guida-al-framework-spring-mvc/

4. Wikipedia: Framework
https://it.wikipedia.org/wiki/Framework

5. Wikipedia: Spring Framework,


https://it.wikipedia.org/wiki/Spring_framework

6. Wikipedia: Inversione di Controllo,


https://it.wikipedia.org/wiki/Inversione_del_controllo

7. Pietro Corasaniti's Blog: Introduzione a Spring,


https://pierocorasaniti.wordpress.com/2013/03/18/introduzione-a-spring/

8. Pietro Corasaniti's Blog: Constructor Dependency Injection,


https://pierocorasaniti.wordpress.com/2013/04/02/constructor-dependecy-injection-cdi/

9. Pietro Corasaniti's Blog: Setter Dependency Injection,


https://pierocorasaniti.wordpress.com/2013/03/21/setter-dependency-injection/

10. Pietro Corasaniti's Blog: Integrazione EJB3 e Spring,


https://pierocorasaniti.wordpress.com/2013/03/28/integrazione-ejb3-e-spring/

27

Anda mungkin juga menyukai