IoC e DI
Il Contenitore Spring è il componente centrale del Spring Framework che gestisce la creazione, la configurazione e il ciclo di vita dei bean (oggetti) all'interno di un'applicazione. Il Contenitore Spring è anche conosciuto come contenitore IoC.
Una dipendenza si riferisce a qualsiasi classe che richiede altri oggetti da iniettare affinché possa funzionare correttamente, e questa catena di dipendenze può continuare indefinitamente. Normalmente, per creare un oggetto con dipendenze, è necessario inizializzarlo esplicitamente utilizzando l'operatore new e specificare la classe.
Ed è qui che entra in gioco Spring con Inversion of Control e Dependency Injection. L'idea è che Spring si assume la responsabilità di creare e gestire le dipendenze. Invece di gestire manualmente la configurazione, è sufficiente annotare le classi necessarie e Spring le crea automaticamente e gestisce il loro ciclo di vita all'interno del proprio contesto.
Una di queste annotazioni è @Component, che si posiziona sopra la classe.
BeanExample.java
123@Component public class BeanExample { }
Questo approccio sposta l'attenzione dalla gestione manuale delle dipendenze, permettendo agli sviluppatori di concentrarsi sulla logica di business mentre Spring si occupa dei compiti infrastrutturali relativi alla creazione degli oggetti e alla gestione delle dipendenze.
Come funziona il contenitore Spring?
Quando l'applicazione viene avviata, il contenitore Spring viene inizializzato. Inizia scansionando le classi alla ricerca di annotazioni come @Component, @Service, @Repository e @Configuration.
@Component è un'annotazione generale che rende una classe gestita da Spring, consentendone la registrazione come bean.
@Service, @Repository e @Controller sono versioni più specializzate di @Component. Svolgono la stessa funzione ma indicano il ruolo specifico della classe: @Service per la logica di business, @Repository per l'accesso ai dati e @Controller per la gestione delle richieste web.
@Configuration viene utilizzata per le classi che contengono definizioni di bean e configurazione dell'applicazione.
Contrassegnando una classe con una di queste annotazioni, si garantisce che diventi un bean all'interno del contesto Spring.
Una volta che le classi sono identificate, il contenitore procede a creare istanze di queste classi annotate, trasformandole di fatto in bean che il contesto Spring gestisce durante l'intero ciclo di vita dell'applicazione.
Durante la creazione dei bean, il contenitore gestisce automaticamente le loro dipendenze tramite la Dependency Injection. Questo processo consente alle classi di ricevere le dipendenze necessarie senza doverle creare o individuare esplicitamente, semplificando così il processo di sviluppo.
Dependency Injection (DI)
Per prima cosa, il contenitore Spring aggiunge al proprio contesto i bean (classi) contrassegnati con le annotazioni @Component, @Service, @Repository e @Configuration. Successivamente, fornisce questi bean a qualsiasi oggetto che ne faccia richiesta.
Esempio reale
Immagina di sviluppare un negozio online. Hai una classe OrderService che gestisce gli ordini e una classe PaymentService che gestisce i pagamenti. Invece di creare manualmente un'istanza di PaymentService all'interno di OrderService, puoi lasciare che sia il contenitore Spring a creare e iniettare PaymentService in OrderService.
OrderService.java
PaymentService.java
1234567891011121314@Service public class OrderService { private final PaymentService paymentService; public OrderService(PaymentService paymentService) { this.paymentService = paymentService; } public void placeOrder() { System.out.println("Placing order..."); paymentService.processPayment(); } }
Nella classe OrderService, è presente un campo paymentService che viene inizializzato con l'esatto tipo necessario (PaymentService). Si noti che non abbiamo esplicitamente inizializzato questo oggetto, Spring lo ha fatto per noi!
Se non avessimo annotato PaymentService con @Service, questo bean non sarebbe stato aggiunto al contesto Spring, e si sarebbe verificato un errore che indica che Spring non riesce a trovare tale bean.
@Autowired
È possibile utilizzare anche l'annotazione @Autowired, che indica al contenitore Spring di iniettare l'oggetto appropriato nel campo.
OrderService.java
123456789101112131415@Service public class OrderService { private final PaymentService paymentService; @Autowired public OrderService(PaymentService paymentService) { this.paymentService = paymentService; } public void placeOrder() { System.out.println("Placing order..."); paymentService.processPayment(); } }
In Spring, a partire dalla versione 4.3, l'utilizzo dell'annotazione @Autowired non è più necessario quando si iniettano dipendenze tramite un costruttore se nella classe è presente un solo costruttore. Spring determina automaticamente che questo costruttore deve essere utilizzato per l'iniezione delle dipendenze.
Quali sono i diversi tipi di Bean?
Immagina di avere una singola macchina da caffè in un bar. Ogni volta che un cliente ordina un caffè, il barista utilizza sempre questa stessa macchina da caffè per preparare ogni tazza. La macchina da caffè è sempre la stessa, non una nuova per ogni ordine.
Allo stesso modo, in Spring, quando inietti un bean dal contesto Spring, Spring ti fornisce ogni volta la stessa istanza di quel bean. Questo è noto come singleton scope. Proprio come la macchina da caffè nel bar, Spring garantisce che tu riceva sempre lo stesso oggetto invece di crearene uno nuovo ogni volta.
Singleton
È possibile impostare il tipo utilizzando l'annotazione @Scope e specificare singleton negli attributi.
SingletonService.
12345@Service @Scope("singleton") public class SingletonService { // Class for handling business logic }
Prototype
PrototypeService.java
12345@Service @Scope("prototype") public class PrototypeService { // Class for handling business logic }
Si applica la stessa procedura, ma si specifica prototype negli attributi. Questo garantisce che ogni volta che si inietta questo bean, verrà restituito un nuovo oggetto.
Sommario
In questo capitolo su IoC (Inversione del Controllo) e DI (Iniezione delle Dipendenze), abbiamo esaminato come Spring gestisce la creazione e il ciclo di vita dei bean tramite il proprio contenitore, consentendo l'iniezione automatica delle dipendenze.
Abbiamo discusso dello scope predefinito singleton, in cui una singola istanza di un bean viene riutilizzata, e dello scope prototype, che crea una nuova istanza per ogni richiesta, evidenziando come questi scope influenzano la gestione degli oggetti e la progettazione dell'applicazione.
1. Che cos'è l'Inversion of Control (IoC) in Spring?
2. Quale principio è alla base dell'Dependency Injection (DI)?
Grazie per i tuoi commenti!
Chieda ad AI
Chieda ad AI
Chieda pure quello che desidera o provi una delle domande suggerite per iniziare la nostra conversazione
Awesome!
Completion rate improved to 3.45
IoC e DI
Scorri per mostrare il menu
Il Contenitore Spring è il componente centrale del Spring Framework che gestisce la creazione, la configurazione e il ciclo di vita dei bean (oggetti) all'interno di un'applicazione. Il Contenitore Spring è anche conosciuto come contenitore IoC.
Una dipendenza si riferisce a qualsiasi classe che richiede altri oggetti da iniettare affinché possa funzionare correttamente, e questa catena di dipendenze può continuare indefinitamente. Normalmente, per creare un oggetto con dipendenze, è necessario inizializzarlo esplicitamente utilizzando l'operatore new e specificare la classe.
Ed è qui che entra in gioco Spring con Inversion of Control e Dependency Injection. L'idea è che Spring si assume la responsabilità di creare e gestire le dipendenze. Invece di gestire manualmente la configurazione, è sufficiente annotare le classi necessarie e Spring le crea automaticamente e gestisce il loro ciclo di vita all'interno del proprio contesto.
Una di queste annotazioni è @Component, che si posiziona sopra la classe.
BeanExample.java
123@Component public class BeanExample { }
Questo approccio sposta l'attenzione dalla gestione manuale delle dipendenze, permettendo agli sviluppatori di concentrarsi sulla logica di business mentre Spring si occupa dei compiti infrastrutturali relativi alla creazione degli oggetti e alla gestione delle dipendenze.
Come funziona il contenitore Spring?
Quando l'applicazione viene avviata, il contenitore Spring viene inizializzato. Inizia scansionando le classi alla ricerca di annotazioni come @Component, @Service, @Repository e @Configuration.
@Component è un'annotazione generale che rende una classe gestita da Spring, consentendone la registrazione come bean.
@Service, @Repository e @Controller sono versioni più specializzate di @Component. Svolgono la stessa funzione ma indicano il ruolo specifico della classe: @Service per la logica di business, @Repository per l'accesso ai dati e @Controller per la gestione delle richieste web.
@Configuration viene utilizzata per le classi che contengono definizioni di bean e configurazione dell'applicazione.
Contrassegnando una classe con una di queste annotazioni, si garantisce che diventi un bean all'interno del contesto Spring.
Una volta che le classi sono identificate, il contenitore procede a creare istanze di queste classi annotate, trasformandole di fatto in bean che il contesto Spring gestisce durante l'intero ciclo di vita dell'applicazione.
Durante la creazione dei bean, il contenitore gestisce automaticamente le loro dipendenze tramite la Dependency Injection. Questo processo consente alle classi di ricevere le dipendenze necessarie senza doverle creare o individuare esplicitamente, semplificando così il processo di sviluppo.
Dependency Injection (DI)
Per prima cosa, il contenitore Spring aggiunge al proprio contesto i bean (classi) contrassegnati con le annotazioni @Component, @Service, @Repository e @Configuration. Successivamente, fornisce questi bean a qualsiasi oggetto che ne faccia richiesta.
Esempio reale
Immagina di sviluppare un negozio online. Hai una classe OrderService che gestisce gli ordini e una classe PaymentService che gestisce i pagamenti. Invece di creare manualmente un'istanza di PaymentService all'interno di OrderService, puoi lasciare che sia il contenitore Spring a creare e iniettare PaymentService in OrderService.
OrderService.java
PaymentService.java
1234567891011121314@Service public class OrderService { private final PaymentService paymentService; public OrderService(PaymentService paymentService) { this.paymentService = paymentService; } public void placeOrder() { System.out.println("Placing order..."); paymentService.processPayment(); } }
Nella classe OrderService, è presente un campo paymentService che viene inizializzato con l'esatto tipo necessario (PaymentService). Si noti che non abbiamo esplicitamente inizializzato questo oggetto, Spring lo ha fatto per noi!
Se non avessimo annotato PaymentService con @Service, questo bean non sarebbe stato aggiunto al contesto Spring, e si sarebbe verificato un errore che indica che Spring non riesce a trovare tale bean.
@Autowired
È possibile utilizzare anche l'annotazione @Autowired, che indica al contenitore Spring di iniettare l'oggetto appropriato nel campo.
OrderService.java
123456789101112131415@Service public class OrderService { private final PaymentService paymentService; @Autowired public OrderService(PaymentService paymentService) { this.paymentService = paymentService; } public void placeOrder() { System.out.println("Placing order..."); paymentService.processPayment(); } }
In Spring, a partire dalla versione 4.3, l'utilizzo dell'annotazione @Autowired non è più necessario quando si iniettano dipendenze tramite un costruttore se nella classe è presente un solo costruttore. Spring determina automaticamente che questo costruttore deve essere utilizzato per l'iniezione delle dipendenze.
Quali sono i diversi tipi di Bean?
Immagina di avere una singola macchina da caffè in un bar. Ogni volta che un cliente ordina un caffè, il barista utilizza sempre questa stessa macchina da caffè per preparare ogni tazza. La macchina da caffè è sempre la stessa, non una nuova per ogni ordine.
Allo stesso modo, in Spring, quando inietti un bean dal contesto Spring, Spring ti fornisce ogni volta la stessa istanza di quel bean. Questo è noto come singleton scope. Proprio come la macchina da caffè nel bar, Spring garantisce che tu riceva sempre lo stesso oggetto invece di crearene uno nuovo ogni volta.
Singleton
È possibile impostare il tipo utilizzando l'annotazione @Scope e specificare singleton negli attributi.
SingletonService.
12345@Service @Scope("singleton") public class SingletonService { // Class for handling business logic }
Prototype
PrototypeService.java
12345@Service @Scope("prototype") public class PrototypeService { // Class for handling business logic }
Si applica la stessa procedura, ma si specifica prototype negli attributi. Questo garantisce che ogni volta che si inietta questo bean, verrà restituito un nuovo oggetto.
Sommario
In questo capitolo su IoC (Inversione del Controllo) e DI (Iniezione delle Dipendenze), abbiamo esaminato come Spring gestisce la creazione e il ciclo di vita dei bean tramite il proprio contenitore, consentendo l'iniezione automatica delle dipendenze.
Abbiamo discusso dello scope predefinito singleton, in cui una singola istanza di un bean viene riutilizzata, e dello scope prototype, che crea una nuova istanza per ogni richiesta, evidenziando come questi scope influenzano la gestione degli oggetti e la progettazione dell'applicazione.
1. Che cos'è l'Inversion of Control (IoC) in Spring?
2. Quale principio è alla base dell'Dependency Injection (DI)?
Grazie per i tuoi commenti!