Anotación Spring @Autowired

La anotación @Autowired de Spring se utiliza para la inyección automática de dependencias. El framework de Spring está construido sobre la inyección de dependencias e inyectamos las dependencias de clase a través del archivo de configuración de beans de Spring.

Spring @Autowired Anotación

Normalmente proporcionamos detalles de configuración de beans en el archivo de configuración de beans de Spring y también especificamos los beans que se inyectarán en otros beans usando el atributo ref. Pero el framework de Spring también proporciona características de autoconexión donde no necesitamos proporcionar detalles de inyección de beans explícitamente. Hay diferentes formas a través de las cuales podemos conectar automáticamente un bean de Spring.

  1. autowire byName – Para este tipo de autoconexión, se utiliza el método setter para la inyección de dependencias. Además, el nombre de la variable debe ser el mismo en la clase donde inyectaremos la dependencia y en el archivo de configuración de beans de Spring.
  2. autowire byType – Para este tipo de autowiring, se utiliza el tipo de clase. Por lo tanto, solo debe haber una bean configurada para este tipo en el archivo de configuración de beans de Spring.
  3. autowire by constructor – Esto es casi similar al autowire byType, la única diferencia es que se utiliza el constructor para inyectar la dependencia.
  4. autowire by autodetect – Si estás utilizando Spring 3.0 o versiones anteriores, esta es una de las opciones de autowire disponibles. Esta opción se usaba para autowire by constructor o byType, según lo determinado por el contenedor de Spring. Dado que ya tenemos tantas opciones, esta opción está en desuso. No cubriré esta opción en este tutorial.
  5. @Autowired anotación – Podemos utilizar la anotación Spring @Autowired para el autowiring de beans de Spring. La anotación @Autowired se puede aplicar en variables y métodos para el autowiring byType. También podemos usar la anotación @Autowired en el constructor para el autowiring de Spring basado en constructor. Para que la anotación @Autowired funcione, también debemos habilitar la configuración basada en anotaciones en el archivo de configuración de beans de Spring. Esto se puede hacer mediante el elemento context:annotation-config o mediante la definición de una bean de tipo org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.
  6. @Qualifier anotación – Esta anotación se utiliza para evitar conflictos en el mapeo de beans y necesitamos proporcionar el nombre del bean que se utilizará para la autoconexión. De esta manera, podemos evitar problemas cuando se definen múltiples beans para el mismo tipo. Esta anotación generalmente funciona con la anotación @Autowired. Para constructores con múltiples argumentos, podemos usar esta anotación con los nombres de los argumentos en el método.

Por defecto, la autoconexión de beans de Spring está desactivada. El valor predeterminado de la autoconexión de beans de Spring es “default”, lo que significa que no se realizará ninguna autoconexión. El valor de autoconexión “no” también tiene el mismo comportamiento. Para mostrar el uso de la autoconexión de beans de Spring, creemos un proyecto Spring Maven simple. Nuestro proyecto final se verá como en la siguiente imagen. Analicemos cada una de las opciones de autoconexión una por una. Para ello, crearemos un bean de modelo y una clase de servicio donde inyectaremos el bean de modelo.

Spring @Autowired Anotación – Dependencias Maven

Para la autoconexión de Spring, no necesitamos agregar dependencias adicionales. Nuestro archivo pom.xml tiene dependencias del núcleo del framework de Spring y se ve así.

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

Primavera @Autowired Anotación – Modelo de Bean

Creemos un Bean Java simple, llamado Empleado. Este bean tendrá una única propiedad con métodos getter y setter. Inicializaremos el valor de esta propiedad en el archivo de configuración de bean de 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;
	}
}

Primavera @Autowired Anotación – Clase de Servicio

Creemos nuestra clase de servicio en la cual inyectaremos el bean Empleado mediante la autowiring de primavera.

package com.journaldev.spring.autowiring.service;

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

public class EmployeeService {

	private Employee employee;

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

	// constructor predeterminado para evitar BeanInstantiationException para autowire
	// porNombre o porTipo
	public EmployeeService() {
		System.out.println("Default Constructor used");
	}

	// utilizado para autowire porNombre y porTipo
	public void setEmployee(Employee emp) {
		this.employee = emp;
	}

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

Utilizaremos la misma clase de servicio para realizar la inyección automática de Spring por nombre, por tipo y por constructor. El método setter se utilizará para la inyección automática de Spring por nombre y por tipo, mientras que la inyección basada en constructor se utilizará mediante el atributo autowire del constructor. Cuando utilizamos la inyección automática de Spring por nombre o por tipo, se utiliza el constructor por defecto. Por eso hemos definido explícitamente el constructor por defecto para el bean EmployeeService.

Spring @Autowired Anotación – Ejemplo de inyección automática por tipo

Creemos una clase separada con la anotación @Autowired de Spring para la inyección automática 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 {

	//La anotación Autowired en variables/setters es equivalente a autowire="byType"
	@Autowired
	private Employee employee;
	
	@Autowired
	public void setEmployee(Employee emp){
		this.employee=emp;
	}
	
	public Employee getEmployee(){
		return this.employee;
	}
}

Tenga en cuenta que he anotado tanto la variable Employee como su método setter con la anotación @Autowired de Spring, sin embargo, solo una de estas es suficiente para la inyección automática del bean de Spring.

La anotación Spring @Autowired y el autowiring de beans por constructor con la anotación @Qualifier Ejemplo

Creemos otra clase de servicio donde utilizaremos la anotación @Autowired para la inyección basada en constructor. También veremos el uso de la anotación @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;

	// La anotación @Autowired en el constructor es equivalente a autowire="constructor"
	@Autowired(required=false)
	public EmployeeAutowiredByConstructorService(@Qualifier("employee") Employee emp){
		this.employee=emp;
	}
	
	public Employee getEmployee() {
		return this.employee;
	}
}

Cuando este bean sea inicializado por el framework Spring, se utilizará el bean con el nombre “employee” para la inyección automática. La anotación @Autowired de Spring acepta un argumento “required” que es un booleano con valor predeterminado TRUE. Podemos definirlo como “false” para que el framework Spring no lance ninguna excepción si no se encuentra ningún bean adecuado para la inyección automática.

Primavera @Autowired Anotación – Archivo de Configuración de Bean

El archivo de configuración de beans de Spring es la parte principal de cualquier aplicación de Spring, veamos cómo se ve nuestro archivo de configuración de beans de Spring y luego analizaremos cada parte de él.

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

Los puntos importantes sobre el archivo de configuración de beans de Spring son:

  • El elemento beans default-autowire se utiliza para definir el método de autowiring por defecto. Aquí estoy definiendo el método de autowiring por defecto como porNombre.
  • El elemento beans default-autowire-candidates se utiliza para proporcionar el patrón para los nombres de beans que se pueden utilizar para el autowiring. Para simplificar, permito que todas las definiciones de beans sean elegibles para el autowiring, sin embargo, si podemos definir algún patrón para el autowiring. Por ejemplo, si solo queremos definiciones de beans DAO para el autowiring, podemos especificarlo como default-autowire-candidates="*DAO".
  • autowire-candidate="false" se utiliza en una definición de bean para hacerla no elegible para el autowiring. Es útil cuando tenemos múltiples definiciones de beans para un solo tipo y queremos que algunas de ellas no sean autowired. Por ejemplo, en las configuraciones de beans de primavera anteriores, el bean “employee1” no se utilizará para el autowiring.
  • El atributo autowire byName, byType y constructor es autoexplicativo, no hay mucho que explicar allí.
  • context:annotation-config se utiliza para habilitar el soporte de configuración basado en anotaciones. Note que los beans employeeAutowiredByTypeService y employeeAutowiredByConstructorService no tienen atributos autowire.

Spring @Autowired Anotación – Programa de Prueba

Ahora que nuestra aplicación de Spring está lista con todos los tipos de autowiring de Spring, escribamos un programa de prueba simple para ver si funciona como se espera o no.

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());
		
		//imprimiendo hashcode para confirmar que todos los objetos son de tipo diferente
		System.out.println(serviceByName.hashCode()+"::"+serviceByType.hashCode()+"::"+serviceByConstructor.hashCode());
		
		//Probando las anotaciones @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();
	}
}

El programa es simple, simplemente creamos el contexto de la aplicación de Spring y lo usamos para obtener diferentes beans e imprimir el nombre del empleado. Cuando ejecutamos la aplicación anterior, obtenemos la siguiente salida.

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 puede ver, para la autovinculación por nombre y por tipo, se utiliza el constructor sin argumentos por defecto para inicializar el bean. Para la autovinculación por constructor, se utiliza el constructor basado en parámetros. A partir del hashcode de todas las variables, hemos confirmado que todos los beans de Spring son objetos diferentes y no se refieren al mismo objeto. Dado que hemos eliminado “employee1” de la lista de beans elegibles para la autovinculación, no hubo confusión en el mapeo de beans. Si eliminamos autowire-candidate="false" de la definición de “employee1”, obtendremos el siguiente mensaje de error al ejecutar el método principal anterior.

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

Eso es todo para la anotación @Autowired de Spring y la característica de autovinculación de Spring. Descargue el proyecto de ejemplo desde el siguiente enlace y analícelo para obtener más información.

Descargar Proyecto de Autovinculación de Beans de Spring

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