Spring @Autowired Anotação

Primavera A anotação @Autowired é usada para injeção automática de dependências. O framework Spring é construído com base na injeção de dependências, e injetamos as dependências da classe por meio do arquivo de configuração de feijões do Spring.

Spring @Autowired Anotação

Normalmente, fornecemos detalhes de configuração do feijão no arquivo de configuração de feijões do Spring e também especificamos os feijões que serão injetados em outros feijões usando o atributo ref. No entanto, o framework Spring também fornece recursos de autowiring, onde não precisamos fornecer detalhes de injeção de feijão explicitamente. Existem diferentes maneiras de autowire um feijão Spring.

  1. autowire byName – Para este tipo de autowiring, o método setter é usado para a injeção de dependência. Além disso, o nome da variável deve ser o mesmo na classe onde injetaremos a dependência e no arquivo de configuração de feijões do Spring.
  2. autowire byType – Para esse tipo de autowiring, é utilizado o tipo de classe. Portanto, deve haver apenas um bean configurado para esse tipo no arquivo de configuração de beans do Spring.
  3. autowire by constructor – Isso é quase semelhante ao autowire byType, a única diferença é que o construtor é usado para injetar a dependência.
  4. autowire by autodetect – Se você estiver usando o Spring 3.0 ou versões mais antigas, esta é uma das opções de autowire disponíveis. Esta opção era usada para autowire by constructor ou byType, conforme determinado pelo contêiner Spring. Como já temos tantas opções, esta opção está obsoleta. Não vou cobrir esta opção neste tutorial.
  5. @Autowired annotation – Podemos usar a anotação @Autowired do Spring para autowiring de beans. A anotação @Autowired pode ser aplicada em variáveis e métodos para autowiring byType. Também podemos usar a anotação @Autowired no construtor para autowiring de primavera baseado em construtor. Para que a anotação @Autowired funcione, também precisamos habilitar a configuração baseada em anotações no arquivo de configuração de beans do Spring. Isso pode ser feito pelo elemento context:annotation-config ou definindo um bean do tipo org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.
  6. A anotação @Qualifier – Esta anotação é usada para evitar conflitos na mapeação de beans e precisamos fornecer o nome do bean que será usado para a autoconfiguração. Desta forma, podemos evitar problemas onde múltiplos beans são definidos para o mesmo tipo. Esta anotação geralmente funciona com a anotação @Autowired. Para construtores com múltiplos argumentos, podemos usar esta anotação com os nomes dos argumentos no método.

Por padrão, a autoconfiguração de beans do Spring está desativada. O valor padrão da autowire do bean Spring é “default”, o que significa que nenhuma autoconfiguração será realizada. O valor de autowire “no” também tem o mesmo comportamento. Para mostrar o uso da autoconfiguração de beans do Spring, vamos criar um projeto Maven Spring simples. Nosso projeto final ficará parecido com a imagem abaixo. Vamos analisar cada uma das opções de autoconfiguração uma por uma. Para isso, criaremos um bean de modelo e uma classe de serviço onde injetaremos o bean de modelo.

Spring @Autowired Anotação – Dependências do Maven

Para a autoconfiguração do Spring, não precisamos adicionar nenhuma dependência adicional. Nosso arquivo pom.xml possui dependências principais do framework Spring e parece com o abaixo.

<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.springframework.samples</groupId>
	<artifactId>SpringBeanAutowiring</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>

		<!-- Generic properties -->
		<java.version>1.6</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<!-- Spring -->
		<spring-framework.version>4.0.2.RELEASE</spring-framework.version>

		<!-- Logging -->
		<logback.version>1.0.13</logback.version>
		<slf4j.version>1.7.5</slf4j.version>

	</properties>

	<dependencies>
		<!-- Spring and Transactions -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring-framework.version}</version>
		</dependency>

		<!-- Logging with SLF4J & LogBack -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>runtime</scope>
		</dependency>

	</dependencies>
</project>

Anotação de @Autowired – Modelo de Bean

Vamos criar um Bean Java simples, chamado Employee. Este bean terá uma única propriedade com métodos getter e setter. Vamos inicializar o valor desta propriedade no arquivo de configuração do bean do Spring.

package com.journaldev.spring.autowiring.model;

public class Employee {

	private String name;

	public String getName() {
		return name;
	}

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

Anotação de @Autowired – Classe de Serviço

Vamos criar nossa classe de serviço na qual iremos injetar o bean Employee através da autowiring do Spring.

package com.journaldev.spring.autowiring.service;

import com.journaldev.spring.autowiring.model.Employee;

public class EmployeeService {

	private Employee employee;

	// o construtor é usado para autowire por construtor
	public EmployeeService(Employee emp) {
		System.out.println("Autowiring by constructor used");
		this.employee = emp;
	}

	// construtor padrão para evitar BeanInstantiationException para autowire
	// porNome ou porTipo
	public EmployeeService() {
		System.out.println("Default Constructor used");
	}

	// usado para autowire porNome e porTipo
	public void setEmployee(Employee emp) {
		this.employee = emp;
	}

	public Employee getEmployee() {
		return this.employee;
	}
}

Vamos usar a mesma classe de serviço para realizar a autowiring do Spring porNome, porTipo e por construtor. O método setter será usado para a autowiring do Spring porNome e porTipo, enquanto a injeção baseada em construtor será usada pelo atributo autowire do construtor. Quando usamos a autowire do Spring porNome ou porTipo, o construtor padrão é utilizado. Por isso, definimos explicitamente o construtor padrão para o bean EmployeeService.

Primavera @Autowired Anotação – Exemplo de autowiring porTipo

Vamos criar uma classe separada com a anotação @Autowired do Spring para autowiring porTipo.

package com.journaldev.spring.autowiring.service;

import org.springframework.beans.factory.annotation.Autowired;

import com.journaldev.spring.autowiring.model.Employee;

public class EmployeeAutowiredByTypeService {

	// A anotação Autowired em variáveis/setters é equivalente a autowire="byType"
	@Autowired
	private Employee employee;
	
	@Autowired
	public void setEmployee(Employee emp){
		this.employee=emp;
	}
	
	public Employee getEmployee(){
		return this.employee;
	}
}

Observe que anotei tanto a variável Employee quanto o seu método setter com a anotação @Autowired do Spring, no entanto, apenas um deles é suficiente para a autowiring do bean Spring.

Spring @Autowired Anotação e Exemplo de Autowiring de Feijão por Construtor

Vamos criar outra classe de serviço onde usaremos a anotação @Autowired para injeção baseada em construtor. Também veremos o uso da anotação @Qualifier.

package com.journaldev.spring.autowiring.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import com.journaldev.spring.autowiring.model.Employee;

public class EmployeeAutowiredByConstructorService {

	private Employee employee;

	//A anotação Autowired no Construtor é equivalente a autowire="constructor"
	@Autowired(required=false)
	public EmployeeAutowiredByConstructorService(@Qualifier("employee") Employee emp){
		this.employee=emp;
	}
	
	public Employee getEmployee() {
		return this.employee;
	}
}

Quando este feijão for inicializado pelo framework Spring, o feijão com nome “employee” será usado para autowiring. A anotação @Autowired do Spring aceita um argumento “required” que é um booleano com valor padrão TRUE. Podemos defini-lo como “false” para que o framework Spring não lance nenhuma exceção se nenhum feijão adequado for encontrado para autowiring.

**Anotação Spring** – Arquivo de Configuração do Bean

O arquivo de configuração do bean Spring é a parte principal de qualquer aplicativo Spring. Vamos ver como nosso arquivo de configuração do bean Spring se parece e então vamos examinar cada parte dele.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="https://www.springframework.org/schema/context"
	xsi:schemaLocation="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-4.0.xsd"
		
		default-autowire="byName" default-autowire-candidates="*" >

<bean name="employee" class="com.journaldev.spring.autowiring.model.Employee">
	<property name="name" value="Pankaj"></property>
</bean>

<bean name="employee1" class="com.journaldev.spring.autowiring.model.Employee" autowire-candidate="false">
	<property name="name" value="Dummy Name"></property>
</bean>

<!-- autowiring byName, bean name should be same as the property name -->
<bean name="employeeServiceByName" class="com.journaldev.spring.autowiring.service.EmployeeService" autowire="byName" />

<!-- autowiring byType, there should be only one bean definition for the mapping -->
<bean name="employeeServiceByType" class="com.journaldev.spring.autowiring.service.EmployeeService" autowire="byType" />

<!-- autowiring by constructor -->
<bean name="employeeServiceConstructor" class="com.journaldev.spring.autowiring.service.EmployeeService" autowire="constructor" />

<!-- Enable Annotation based configuration -->
<context:annotation-config />

<!-- using @Autowiring annotation in below beans, byType and constructor -->
<bean name="employeeAutowiredByTypeService" class="com.journaldev.spring.autowiring.service.EmployeeAutowiredByTypeService" />
<bean name="employeeAutowiredByConstructorService" class="com.journaldev.spring.autowiring.service.EmployeeAutowiredByConstructorService" />
</beans>

Pontos importantes sobre o arquivo de configuração do bean Spring:

  • Elemento de feijão default-autowire é usado para definir o método de auto-configuração padrão. Aqui estou definindo o método de auto-configuração padrão como porNome.
  • O elemento beans default-autowire-candidates é usado para fornecer o padrão para os nomes de beans que podem ser usados para auto-configuração. Para simplicidade, estou permitindo que todas as definições de bean sejam elegíveis para auto-configuração, no entanto, se pudermos definir algum padrão para auto-configuração. Por exemplo, se quisermos apenas definições de bean DAO para auto-configuração, podemos especificá-lo como default-autowire-candidates="*DAO".
  • autowire-candidate="false" é usado em uma definição de bean para torná-lo inelegível para auto-configuração. É útil quando temos várias definições de bean para um único tipo e queremos que algumas delas não sejam auto-configuradas. Por exemplo, nas configurações de bean Spring acima, o bean “employee1” não será usado para auto-configuração.
  • autowire atributo byName, byType e constructor são autoexplicativos, não há muito a explicar aqui.
  • context:annotation-config é usado para habilitar o suporte à configuração baseada em anotações. Observe que os beans employeeAutowiredByTypeService e employeeAutowiredByConstructorService não têm atributos autowire.

Spring @Autowired Anotação – Programa de Teste

Agora que nossa aplicação Spring está pronta com todos os tipos de autowiring do Spring, vamos escrever um programa de teste simples para ver se funciona como esperado ou não.

package com.journaldev.spring.autowiring.main;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.journaldev.spring.autowiring.service.EmployeeAutowiredByConstructorService;
import com.journaldev.spring.autowiring.service.EmployeeAutowiredByTypeService;
import com.journaldev.spring.autowiring.service.EmployeeService;

public class SpringMain {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
		
		EmployeeService serviceByName = ctx.getBean("employeeServiceByName", EmployeeService.class);
		
		System.out.println("Autowiring byName. Employee Name="+serviceByName.getEmployee().getName());
		
		EmployeeService serviceByType = ctx.getBean("employeeServiceByType", EmployeeService.class);
		
		System.out.println("Autowiring byType. Employee Name="+serviceByType.getEmployee().getName());
		
		EmployeeService serviceByConstructor = ctx.getBean("employeeServiceConstructor", EmployeeService.class);
		
		System.out.println("Autowiring by Constructor. Employee Name="+serviceByConstructor.getEmployee().getName());
		
		//imprimindo hashcode para confirmar que todos os objetos são de tipos diferentes
		System.out.println(serviceByName.hashCode()+"::"+serviceByType.hashCode()+"::"+serviceByConstructor.hashCode());
		
		//Testando as anotações @Autowired
		EmployeeAutowiredByTypeService autowiredByTypeService = ctx.getBean("employeeAutowiredByTypeService",EmployeeAutowiredByTypeService.class);
		
		System.out.println("@Autowired byType. Employee Name="+autowiredByTypeService.getEmployee().getName());

		EmployeeAutowiredByConstructorService autowiredByConstructorService = ctx.getBean("employeeAutowiredByConstructorService",EmployeeAutowiredByConstructorService.class);
		
		System.out.println("@Autowired by Constructor. Employee Name="+autowiredByConstructorService.getEmployee().getName());

		ctx.close();
	}
}

O programa é simples, estamos apenas criando o contexto da aplicação Spring e usando-o para obter diferentes beans e imprimir o nome do funcionário. Quando executamos a aplicação acima, obtemos a seguinte saída.

Mar 31, 2014 10:41:58 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3fa99295: startup date [Mon Mar 31 22:41:58 PDT 2014]; root of context hierarchy
Mar 31, 2014 10:41:58 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring.xml]
Default Constructor used
Default Constructor used
Autowiring by constructor used
Autowiring byName. Employee Name=Pankaj
Autowiring byType. Employee Name=Pankaj
Autowiring by Constructor. Employee Name=Pankaj
21594592::15571401::1863015320
@Autowired byType. Employee Name=Pankaj
@Autowired by Constructor. Employee Name=Pankaj
Mar 31, 2014 10:41:58 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@3fa99295: startup date [Mon Mar 31 22:41:58 PDT 2014]; root of context hierarchy

Como você pode ver, para o autowire byName e byType, o construtor padrão sem argumentos é usado para inicializar o bean. Para o autowire por construtor, o construtor baseado em parâmetros é utilizado. A partir do hashcode de todas as variáveis, confirmamos que todos os beans Spring são objetos diferentes e não se referem ao mesmo objeto. Uma vez que removemos “employee1” da lista de beans elegíveis para autowiring, não houve confusão na mapeação de beans. Se removermos autowire-candidate="false" da definição de “employee1”, receberemos a seguinte mensagem de erro ao executar o método principal acima.

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'employeeServiceByType' defined in class path resource [spring.xml]: Unsatisfied dependency expressed through bean property 'employee': : No qualifying bean of type [com.journaldev.spring.autowiring.model.Employee] is defined: expected single matching bean but found 2: employee,employee1; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.journaldev.spring.autowiring.model.Employee] is defined: expected single matching bean but found 2: employee,employee1
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1278)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1170)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
	at com.journaldev.spring.autowiring.main.SpringMain.main(SpringMain.java:12)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.journaldev.spring.autowiring.model.Employee] is defined: expected single matching bean but found 2: employee,employee1
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:967)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1263)
	... 13 more

Isso é tudo para a Anotação Spring @Autowired e a funcionalidade de autowiring do Spring. Por favor, faça o download do projeto de exemplo a partir do link abaixo e analise-o para aprender mais.

Download do Projeto de Autowiring de Beans do Spring

Source:
https://www.digitalocean.com/community/tutorials/spring-autowired-annotation