Anotação @Autowired do Spring

A anotação @Autowired do Spring é usada para injeção automática de dependência. O framework Spring é construído sobre injeção de dependência e injetamos as dependências da classe através do arquivo de configuração do feijão Spring.

O Spring @Autowired Anotação

Normalmente fornecemos detalhes de configuração de feijão no arquivo de configuração de feijão Spring e também especificamos os feijões que serão injetados em outros feijões usando o atributo ref. Mas 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 pelas quais podemos autowire um feijão Spring.

  1. autowire byName – Para este tipo de autowiring, o método setter é usado para 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 do feijão Spring.
  2. autowire byType – Para este tipo de autowiring, é utilizado o tipo de classe. Portanto, deve haver apenas um bean configurado para este 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. Essa 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 do Spring. 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 construtor baseado no Spring. 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 autowiring. 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 autowiring de beans Spring está desativada. O valor padrão de autowire de bean Spring é “default”, o que significa que nenhuma autowiring será realizada. O valor de autowire “no” também tem o mesmo comportamento. Para demonstrar o uso da autowiring de bean Spring, vamos criar um projeto Spring Maven simples. Nosso projeto final ficará como a imagem abaixo. Vamos analisar cada uma das opções de autowire uma por uma. Para isso, criaremos um bean Model e uma classe de serviço onde injetaremos o bean model.

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

Para a autowiring Spring, não precisamos adicionar dependências adicionais. Nosso arquivo pom.xml tem dependências principais do framework Spring e parece com o seguinte.

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

Annotation @Autowired da Primavera – Modelo Bean

Vamos criar um simples Bean Java, 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 da primavera.

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

Annotation @Autowired da Primavera – Classe de Serviço

Vamos criar nossa classe de serviço na qual injetaremos o bean Employee através da autoconfiguração da primavera.

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 por nome, por tipo e por construtor. O método setter será usado para a autowiring do Spring por nome e por tipo, enquanto a injeção baseada em construtor será usada pelo atributo de autowire do construtor. Quando usamos a autowire do Spring por nome ou por tipo, o construtor padrão é utilizado. É por isso que definimos explicitamente o construtor padrão para o bean EmployeeService.

Spring @Autowired Anotação – Exemplo de autowiring por tipo

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

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 seu método setter com a anotação Spring @Autowired, no entanto, apenas uma delas é suficiente para a autowiring do bean do Spring.

Spring @Autowired Anotação e @Qualifier Exemplo de injeção de Bean 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 bean for inicializado pelo framework Spring, o bean com o 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 bean adequado for encontrado para autowiring.

Anotação de Primavera @Autowired – Arquivo de Configuração de Feijão

O arquivo de configuração de feijão Spring é a parte principal de qualquer aplicativo Spring, vamos ver como nosso arquivo de configuração de feijão Spring parece e então vamos analisar 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 de feijão Spring são:

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

` `Spring ` A Anotação `@Autowired – Programa de Teste `` `

` Agora que nossa aplicação Spring está pronta com todos os tipos de autowiring 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 o 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 autowire byName e byType, o construtor padrão sem argumentos é usado para inicializar o bean. Para autowire by constructor, é utilizado o construtor baseado em parâmetros. A partir do hashcode de todas as variáveis, confirmamos que todos os beans do Spring são objetos diferentes e não referem ao mesmo objeto. Como removemos “employee1” da lista de beans elegíveis para autowiring, não houve confusão no mapeamento de beans. Se removermos autowire-candidate="false" da definição de “employee1”, receberemos a mensagem de erro abaixo 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, baixe o projeto de exemplo no 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