IoC Spring, Exemplo de Tutorial de Beans Spring

Bem-vindo ao Tutorial Exemplo do Spring IoC. O Spring Framework é construído sobre o princípio da Inversão de Controle. Injeção de dependência é a técnica para implementar IoC em aplicações.

Spring IoC

Hoje vamos olhar para o Container IoC do Spring. Também passaremos pelo Spring Bean. Abaixo está a tabela de conteúdos para navegação rápida para diferentes seções do tutorial do Spring IoC.

  1. Spring IoC
  2. Spring Bean
  3. Escopos do Spring Bean
  4. Configuração do Spring Bean
  5. Exemplo de Spring IoC e Spring Bean
    1. Configuração de Spring Bean Baseada em XML
    2. Configuração de Spring Bean Baseada em Anotações
    3. Configuração de Spring Bean Baseada em Java

Contêiner IoC do Spring

O IoC do Spring é o mecanismo para alcançar o desacoplamento entre as dependências dos objetos. Para obter um desacoplamento flexível e vinculação dinâmica dos objetos em tempo de execução, as dependências dos objetos são injetadas por outros objetos montadores. O contêiner IoC do Spring é o programa que injeta dependências em um objeto e o prepara para o nosso uso. Já vimos como podemos usar Injeção de Dependência do Spring para implementar o IoC em nossas aplicações. As classes do contêiner IoC do Spring fazem parte dos pacotes org.springframework.beans e org.springframework.context. O contêiner IoC do Spring nos fornece diferentes maneiras de desacoplar as dependências do objeto. BeanFactory é a interface raiz do contêiner IoC do Spring. ApplicationContext é a interface filha da interface BeanFactory que fornece recursos de Spring AOP, i18n, etc. Algumas das interfaces filhas úteis de ApplicationContext são ConfigurableApplicationContext e WebApplicationContext. O Spring Framework fornece várias classes de implementação úteis do ApplicationContext que podemos usar para obter o contexto do Spring e, em seguida, o Bean do Spring. Algumas das implementações úteis do ApplicationContext que usamos são;

  • AnnotationConfigApplicationContext: Se estivermos usando o Spring em aplicativos Java independentes e usando anotações para configuração, podemos usar isso para inicializar o contêiner e obter os objetos do bean.
  • ClassPathXmlApplicationContext: Se tivermos um arquivo de configuração XML para beans do Spring em um aplicativo independente, podemos usar esta classe para carregar o arquivo e obter o objeto do contêiner.
  • FileSystemXmlApplicationContext: Similar ao ClassPathXmlApplicationContext, exceto que o arquivo de configuração XML pode ser carregado de qualquer lugar no sistema de arquivos.
  • AnnotationConfigWebApplicationContext e XmlWebApplicationContext para aplicativos web.

Normalmente, se você estiver trabalhando em um aplicativo Spring MVC e seu aplicativo estiver configurado para usar o Spring Framework, o contêiner Spring IoC é inicializado quando o aplicativo inicia e, quando um bean é solicitado, as dependências são injetadas automaticamente. No entanto, para um aplicativo independente, você precisa inicializar o contêiner em algum lugar do aplicativo e depois usá-lo para obter os beans do Spring.

Bean do Spring

Um Bean do Spring não é nada especial, qualquer objeto no framework Spring que inicializamos por meio do contêiner Spring é chamado de Bean do Spring. Qualquer classe Java POJO normal pode ser um Bean do Spring se estiver configurada para ser inicializada via contêiner, fornecendo informações de metadados de configuração.

Escopos de Beans do Spring

Existem cinco escopos definidos para os Spring Beans.

  1. singleton – Apenas uma instância do bean será criada para cada contêiner. Este é o escopo padrão para os beans Spring. Ao usar este escopo, certifique-se de que o bean não tenha variáveis de instância compartilhadas, caso contrário, pode levar a problemas de inconsistência de dados.
  2. prototype – Uma nova instância será criada sempre que o bean for solicitado.
  3. request – Este é o mesmo que o escopo de protótipo, no entanto, é destinado a ser usado para aplicativos da web. Uma nova instância do bean será criada para cada solicitação HTTP.
  4. session – Um novo bean será criado para cada sessão HTTP pelo contêiner.
  5. global-session – Isso é usado para criar beans de sessão global para aplicativos de Portlet.

O Spring Framework é extensível e podemos criar nossos próprios escopos também. No entanto, na maioria das vezes, estamos satisfeitos com os escopos fornecidos pelo framework.

Configuração de Bean do Spring

O Spring Framework fornece três maneiras de configurar beans a serem usados na aplicação.

  1. Configuração Baseada em Anotações – Utilizando anotações como @Service ou @Component. Detalhes de escopo podem ser fornecidos com a anotação @Scope.
  2. Configuração Baseada em XML – Criando um arquivo de configuração XML do Spring para configurar os beans. Se estiver usando o framework Spring MVC, a configuração baseada em XML pode ser carregada automaticamente escrevendo algum código básico no arquivo web.xml.
  3. Configuração Baseada em Java – A partir do Spring 3.0, podemos configurar beans do Spring usando programas Java. Algumas anotações importantes usadas para a configuração baseada em Java são @Configuration, @ComponentScan e @Bean.

Projeto Exemplo de IoC e Bean do Spring

Vamos dar uma olhada nos diferentes aspectos do contêiner Spring IoC e nas configurações de beans do Spring em um projeto Spring simples. Para o meu exemplo, estou criando um projeto Spring MVC no Spring Tool Suite. Se você é novo no Spring Tool Suite e no Spring MVC, por favor, leia Tutorial Spring MVC com Spring Tool Suite. A estrutura final do projeto parece com a imagem abaixo. Vamos analisar os diferentes componentes do projeto Spring IoC e Spring Bean um por um.

Configuração de Bean Spring Baseada em XML

MyBean é uma classe Java POJO simples.

package com.journaldev.spring.beans;

public class MyBean {

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

Arquivo XML de Configuração do Spring

código 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>

Observe que MyBean é configurado usando o elemento bean com escopo singleton.

Configuração de Bean Spring Baseada em Anotações

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;
	}
	
}

MeuAnnotatedBean é configurado usando @Service e o escopo é definido como Solicitação.

Classe Controladora Spring IoC

A classe HomeController irá lidar com as requisições HTTP para a página inicial da aplicação. Injetaremos nossos beans do Spring nesta classe controladora através do contêiner 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";
	}
	
}

Descritor de Implantação

Devemos configurar nossa aplicação para o Framework Spring para que os metadados de configuração sejam carregados e o contexto seja inicializado.

<?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>

Quase toda a configuração acima é código de modelo gerado automaticamente pela ferramenta STS.

Execute a Aplicação de Exemplo de Bean Spring IoC

Agora, quando você lançar a aplicação web, a página inicial será carregada e no console os seguintes logs serão impressos quando você atualizar a página várias vezes.

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

Observe que MyBean está configurado para ser um singleton, então o contêiner sempre retorna a mesma instância e o hashcode é sempre o mesmo. Da mesma forma, para cada solicitação, uma nova instância de MyAnnotatedBean é criada com um hashcode diferente.

Configuração de Feijão Spring Baseada em Java

Para aplicações autônomas, podemos usar configuração baseada em anotações, bem como configuração baseada em XML. O único requisito é inicializar o contexto em algum lugar do programa antes de usá-lo.

package com.journaldev.spring.main;

import java.util.Date;

public class MyService {

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

MyService é uma classe Java simples com alguns métodos.

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();
	}
}

A classe de configuração baseada em anotações que será usada para inicializar o contêiner 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 você estiver procurando por configuração baseada em XML, basta criar o arquivo de configuração XML do Spring e, em seguida, inicializar o contexto com o trecho de código a seguir.

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

Isso é tudo para o tutorial de exemplo do Spring IoC, Escopos de Beans Spring e detalhes de configuração. Faça o download do projeto de exemplo Spring IoC e Spring Bean no link abaixo e brinque com ele para uma melhor compreensão.

Baixar Projeto Spring Beans

Referência: Página Spring.IO para IOC

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