Spring parte3

Vediamo alcune funzionalità avanzate di Spring che l’hanno reso un prodotto di successo.

Le Factory in Spring supportano due modalità di instanziazione dei Bean:

  • Singleton
  • Prototype

Nell modalità Singleton,cioè il comportamento di default, ogni invocazione del metodo getBean(“nomelogico”) restituisce un singleton per quell’oggetto. Avremo quindi un oggetto vero e proprio, accessibile solo da un cliente per volta.

Se più clienti hanno interesse ad un certo servizio, è possibile settare la proprietà Prototype, tramite la quale è possibile ottenere ad ogni invocazione di getBean, una nuova instanza del Bean.

La differenza col modello di EJB nella gestione del pool di instanze, è che in Spring il framework non effettua le callback per l’assegnazione di istanze libere del pool, non gestisce la concorrenza delle chiamate, non mantiene la Sessione, non effettua la Passivazione/Attivazione delle istanze: si limita ad assegnare un’istanza al chiamante, perchè Spring è concepito come modello a container leggero. Per avere tutte queste funzionalità però,il core-developer, può estendere il comportamento di una Factory minimale, DefaultListableBeanFactory, e avere un container che agisce con le caratteristiche scelte.

Un’alternativa all’uso della Factory è usare un ApplicationContext. Tale oggetto di sistema, ci consente di avere funzionalità come gestione del ciclo di vita e delle transazioni, inoltre ci permette di gestire eventi, implementando il classico Observer Pattern, che comunque necessita di un livello di indirettezza, per registrare gli eventi. Perchè un Bean venga agganciato ad un ApplicationContext per potervi interagire, è necessario che esso implementi l’interfaccia ApplicationContextAware che ci impone di settare un riferimento all’ApplicationContext.


public class EmailBean implements ApplicationContextAware {
private List blackList;
public void setBlackList(List blackList) {
this.blackList = blackList;
}
public void setApplicationContext(ApplicationContext ctx) {
this.ctx = ctx;
}

public void sendEmail(String address, String text) {
if (blackList.contains(address)) {
BlackListEvent evt = new BlackListEvent(address, text);
ctx.publishEvent(evt);
return;
}
}
}


In questo caso abbiamo un Bean che si limita a inviare delle email, ma effettua anche un controllo sull’indirizzo del destinatario, se tale indirizzo è in un’ apposita blacklist, allora viene inviato un evento all’ApplicationContext. Ovviamente sull’ApplicationContext è registrato uno specifico Listener per questo tipo di eventi, che effettua una certa operazione per ogni Email inviata ad un indirizzo sulla blacklist.


public class BlackListNotifier implement ApplicationListener {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress)
{
this.notificationAddress = notificationAddress;
}
public void onApplicationEvent(ApplicationEvent evt) {
if (evt instanceof BlackListEvent) {
// invio dell’email di notifica all’indirizzo appropriato
}
}

Un’altra funzionalità importante di Spring è l’AutoWiring. Nell’esempio precedente abbiamo visto come è organizzato il descrittore xml dove andiamo a definire le dipendenze, tramite il tag


<property name="messageProvider">

<ref local="provider"/>

</property>

andiamo a effettuare l’operazione di risoluzione delle dipendenze, che in Spring prende il nome di Wiring. Cosa succede se però non troviamo <bean id="provider"> nel resto del descrittore ? Spring innesca l’AutoWiring, cioè se il metodo che richiede la dipendenza è setMessageProvider allora andrà a cercare la classe di nome MessageProvider. Se neanche quest’ultima si trova, allora andrà a effettuare una ricerca sul tipo del parameter: setMessageProvider(CustomMessageProvider cmp), innescherà una ricerca di una classe CustomMessageProvider.

Ultima feauture da considerare è il Dependency Checking. Spesso può succedere che invocando l’XmlBeanFactory.getBean(“nomebean”); non riusciamo a risolvere una dipendenza, perchè ad esempio è stato fatto male il deployment e non si trova la risorsa indicata. Allora c’è la necessità di effettuare un check delle dipendenze a runtime quando viene invocato il getBean. Ci sono varie modalità di checking:

Modalità possibili:

  • none – nessun check
  • simple – dependency checking effettuato solo per tipi primitivi e collection
  • object – dependency checking effettuato solo per altri bean associati all’interno della stessa factory (collaborator)
  • all – dependency checking effettuato per collaborator, tipi primitivi e collection

Ricordiamoci in generale, che il trade-off in questo caso, è che effettuo un’operazione di controllo, che grava leggermente sulle performance del sistema, ma che offre un beneficio perchè ho la garanzia di evitare gli errori a runtime.

Lascia un Commento

Fill in your details below or click an icon to log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Log Out / Modifica )

Foto Twitter

You are commenting using your Twitter account. Log Out / Modifica )

Foto di Facebook

You are commenting using your Facebook account. Log Out / Modifica )

Connecting to %s

Follow

Get every new post delivered to your Inbox.