Spring IoC, Esempio Tutorial di Bean di Spring

Benvenuti al Tutorial Esempio di Spring IoC. Il Framework Spring è costruito sul principio dell’Inversione di Controllo. Iniezione di dipendenza è la tecnica per implementare IoC nelle applicazioni.

Spring IoC

Oggi esamineremo il Container IoC di Spring. Esamineremo anche Spring Bean. Di seguito è riportato l’indice per una navigazione rapida alle diverse sezioni del tutorial su Spring IoC.

  1. Spring IoC
  2. Spring Bean
  3. Ambiti dei Spring Bean
  4. Configurazione dei Spring Bean
  5. Esempio di Spring IoC e Spring Bean
    1. Configurazione dei Spring Bean basata su XML
    2. Configurazione dei Spring Bean basata su annotazioni
    3. Configurazione dei Spring Bean basata su Java

Contenitore IoC di Spring

Spring IoC è il meccanismo per raggiungere il disaccoppiamento tra le dipendenze degli oggetti. Per ottenere un disaccoppiamento flessibile e un legame dinamico degli oggetti durante l’esecuzione, le dipendenze degli oggetti vengono iniettate da altri oggetti assemblatori. Il contenitore Spring IoC è il programma che inietta le dipendenze in un oggetto e lo rende pronto per il nostro utilizzo. Abbiamo già visto come possiamo utilizzare l’Injection di Dipendenza di Spring per implementare IoC nelle nostre applicazioni. Le classi del contenitore Spring IoC fanno parte dei pacchetti `org.springframework.beans` e `org.springframework.context`. Il contenitore Spring IoC ci fornisce diversi modi per disaccoppiare le dipendenze degli oggetti. `BeanFactory` è l’interfaccia radice del contenitore Spring IoC. `ApplicationContext` è l’interfaccia figlia dell’interfaccia `BeanFactory` che fornisce funzionalità Spring AOP, i18n, ecc. Alcune delle utili interfacce figlie di `ApplicationContext` sono `ConfigurableApplicationContext` e `WebApplicationContext`. Il framework Spring fornisce diverse utili classi di implementazione di ApplicationContext che possiamo utilizzare per ottenere il contesto spring e quindi il Bean Spring. Alcune delle utili implementazioni di ApplicationContext che usiamo sono:

  • AnnotationConfigApplicationContext: Se stiamo utilizzando Spring in applicazioni Java standalone e utilizziamo le annotazioni per la configurazione, allora possiamo utilizzare questa classe per inizializzare il contenitore e ottenere gli oggetti bean.
  • ClassPathXmlApplicationContext: Se abbiamo un file di configurazione xml per i bean di Spring in un’applicazione autonomo, possiamo utilizzare questa classe per caricare il file e ottenere l’oggetto contenitore.
  • FileSystemXmlApplicationContext: Questa è simile a ClassPathXmlApplicationContext, tranne che il file di configurazione xml può essere caricato da qualsiasi posizione nel file system.
  • AnnotationConfigWebApplicationContext e XmlWebApplicationContext per le applicazioni web.

Di solito, se stai lavorando su un’applicazione Spring MVC e la tua applicazione è configurata per utilizzare il framework Spring, il contenitore IoC di Spring viene inizializzato all’avvio dell’applicazione e quando viene richiesto un bean, le dipendenze vengono iniettate automaticamente. Tuttavia, per un’applicazione autonomo, è necessario inizializzare il contenitore in qualche punto dell’applicazione e poi utilizzarlo per ottenere i bean di Spring.

Spring Bean

Un Spring Bean non è nulla di speciale, qualsiasi oggetto nel framework Spring che inizializziamo tramite il contenitore Spring è chiamato Spring Bean. Qualsiasi normale classe Java POJO può essere un Spring Bean se è configurata per essere inizializzata tramite il contenitore fornendo informazioni di metadati di configurazione.

Scope dei Spring Bean

Ci sono cinque ambiti definiti per i Spring Beans.

  1. singleton – Verrà creato solo un’istanza del bean per ogni contenitore. Questo è l’ambito predefinito per i spring beans. Quando si utilizza questo ambito, assicurarsi che il bean non abbia variabili di istanza condivise, altrimenti potrebbe causare problemi di inconsistenza dei dati.
  2. prototype – Verrà creata una nuova istanza ogni volta che il bean viene richiesto.
  3. request – Questo è simile all’ambito prototype, ma è destinato ad essere utilizzato per le applicazioni web. Una nuova istanza del bean verrà creata per ogni richiesta HTTP.
  4. session – Verrà creato un nuovo bean per ogni sessione HTTP dal contenitore.
  5. global-session – Questo viene utilizzato per creare bean di sessione globali per le applicazioni Portlet.

Il Framework Spring è estensibile e possiamo creare i nostri ambiti personalizzati. Tuttavia, nella maggior parte dei casi, ciò che è fornito dal framework è sufficiente.

Configurazione del Bean Spring

Il Framework Spring fornisce tre modi per configurare i bean da utilizzare nell’applicazione.

  1. Configurazione basata su annotazioni – Utilizzando le annotazioni @Service o @Component. I dettagli dello scope possono essere forniti con l’annotazione @Scope.
  2. Configurazione basata su XML – Creando un file di configurazione XML di Spring per configurare i bean. Se si utilizza il framework Spring MVC, la configurazione basata su XML può essere caricata automaticamente scrivendo del codice boilerplate nel file web.xml.
  3. Configurazione basata su Java – A partire da Spring 3.0, possiamo configurare i bean di Spring utilizzando programmi Java. Alcune annotazioni importanti utilizzate per la configurazione basata su Java sono @Configuration, @ComponentScan e @Bean.

Progetto di esempio di Spring IoC e Spring Bean

Guardiamo ai diversi aspetti del contenitore IoC di Spring e alle configurazioni di Spring Bean con un semplice progetto Spring. Per il mio esempio, sto creando un progetto Spring MVC in Spring Tool Suite. Se sei nuovo di Spring Tool Suite e Spring MVC, leggi Tutorial di Spring MVC con Spring Tool Suite. La struttura finale del progetto appare come nell’immagine sotto. Esaminiamo i diversi componenti del contenitore IoC di Spring e del progetto Spring Bean uno per uno.

Configurazione di Spring Bean basata su XML

MyBean è una semplice classe Java POJO.

package com.journaldev.spring.beans;

public class MyBean {

	private String name;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
}

File di configurazione di Spring XML

Codice servlet-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="https://www.springframework.org/schema/beans"
	xmlns:context="https://www.springframework.org/schema/context"
	xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<context:component-scan base-package="com.journaldev.spring" />
	
	<beans:bean name="myBean" class="com.journaldev.spring.beans.MyBean" scope="singleton" ></beans:bean>
	
</beans:beans>

Nota che MyBean è configurato utilizzando l’elemento bean con ambito come singleton.

Configurazione di Spring Bean basata su annotazioni

package com.journaldev.spring.beans;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.web.context.WebApplicationContext;

@Service
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class MyAnnotatedBean {

	private int empId;

	public int getEmpId() {
		return empId;
	}

	public void setEmpId(int empId) {
		this.empId = empId;
	}
	
}

MyAnnotatedBean è configurato utilizzando @Service e lo scope è impostato su Request.

La classe Spring IoC Controller

La classe HomeController gestirà le richieste HTTP per la pagina iniziale dell’applicazione. Inietteremo i nostri bean Spring in questa classe controller attraverso il contenitore WebApplicationContext.

package com.journaldev.spring.controller;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.journaldev.spring.beans.MyAnnotatedBean;
import com.journaldev.spring.beans.MyBean;

@Controller
@Scope("request")
public class HomeController {
		
	private MyBean myBean;
	
	private MyAnnotatedBean myAnnotatedBean;

	@Autowired
	public void setMyBean(MyBean myBean) {
		this.myBean = myBean;
	}

	@Autowired
	public void setMyAnnotatedBean(MyAnnotatedBean obj) {
		this.myAnnotatedBean = obj;
	}
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		System.out.println("MyBean hashcode="+myBean.hashCode());
		System.out.println("MyAnnotatedBean hashcode="+myAnnotatedBean.hashCode());
		
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
		
		String formattedDate = dateFormat.format(date);
		
		model.addAttribute("serverTime", formattedDate );
		
		return "home";
	}
	
}

Descrittore di distribuzione

Dobbiamo configurare la nostra applicazione per il framework Spring in modo che i metadati di configurazione vengano caricati e il contesto venga inizializzato.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

Quasi tutta la configurazione sopra è codice boilerplate generato automaticamente dallo strumento STS.

Esegui l’applicazione di esempio Spring IoC Bean

Ora quando avvierai l’applicazione web, la pagina iniziale verrà caricata e nella console verranno stampati i seguenti log quando aggiorni la pagina più volte.

MyBean hashcode=118267258
MyAnnotatedBean hashcode=1703899856
MyBean hashcode=118267258
MyAnnotatedBean hashcode=1115599742
MyBean hashcode=118267258
MyAnnotatedBean hashcode=516457106

Rileva che MyBean è configurato per essere un singleton, quindi il contenitore restituisce sempre la stessa istanza e l’hashcode è sempre lo stesso. Allo stesso modo, per ogni richiesta, viene creata una nuova istanza di MyAnnotatedBean con un hashcode diverso.

Configurazione del Bean Spring basata su Java

Per le applicazioni autonomo, possiamo utilizzare la configurazione basata su annotazioni e la configurazione basata su XML. L’unico requisito è inizializzare il contesto da qualche parte nel programma prima di utilizzarlo.

package com.journaldev.spring.main;

import java.util.Date;

public class MyService {

	public void log(String msg){
		System.out.println(new Date()+"::"+msg);
	}
}

MyService è una semplice classe Java con alcuni metodi.

package com.journaldev.spring.main;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(value="com.journaldev.spring.main")
public class MyConfiguration {

	@Bean
	public MyService getService(){
		return new MyService();
	}
}

La classe di configurazione basata su annotazioni che verrà utilizzata per inizializzare il contenitore Spring.

package com.journaldev.spring.main;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyMainClass {

	public static void main(String[] args) {
		
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
				MyConfiguration.class);
		MyService service = ctx.getBean(MyService.class);
		
		service.log("Hi");
		
		MyService newService = ctx.getBean(MyService.class);
		System.out.println("service hashcode="+service.hashCode());
		System.out.println("newService hashcode="+newService.hashCode());
		ctx.close();
	}

}

A simple test program where we are initializing the AnnotationConfigApplicationContext context and then using getBean() method to get the instance of MyService. Notice that I am calling getBean method two times and printing the hashcode. Since there is no scope defined for MyService, it should be a singleton and hence hashcode should be the same for both the instances. When we run the above application, we get following console output confirming our understanding.

Sat Dec 28 22:49:18 PST 2013::Hi
service hashcode=678984726
newService hashcode=678984726

Se stai cercando una configurazione basata su XML, basta creare il file di configurazione Spring XML e quindi inizializzare il contesto con il seguente snippet di codice.

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        MyService app = context.getBean(MyService.class);

Questo è tutto per l’esempio tutorial di Spring IoC, dettagli sulle scope e configurazione dei bean Spring. Scarica il progetto di esempio Spring IoC e Spring Bean dal link sottostante e sperimenta per una migliore comprensione.

Scarica il progetto Spring Beans

Riferimento: Pagina Spring.IO per IOC

Source:
https://www.digitalocean.com/community/tutorials/spring-ioc-bean-example-tutorial