Annotation @Autowired de Spring

L’annotation @Autowired de Spring est utilisée pour l’injection automatique de dépendances. Le framework Spring est basé sur l’injection de dépendances et nous injectons les dépendances de classe à travers le fichier de configuration des beans de Spring.

Spring @Autowired Annotation

Habituellement, nous fournissons les détails de configuration des beans dans le fichier de configuration des beans de Spring et nous spécifions également les beans qui seront injectés dans d’autres beans en utilisant l’attribut ref. Mais le framework Spring fournit également des fonctionnalités d’autocâblage où nous n’avons pas besoin de fournir explicitement les détails d’injection de bean. Il existe différentes façons d’autocâbler un bean Spring.

  1. autowire byName – Pour ce type d’autocâblage, la méthode setter est utilisée pour l’injection de dépendances. De plus, le nom de la variable doit être le même dans la classe où nous injecterons la dépendance et dans le fichier de configuration des beans de Spring.
  2. autowire byType – Pour ce type d’autowiring, le type de classe est utilisé. Il ne devrait donc y avoir qu’un seul bean configuré pour ce type dans le fichier de configuration des beans Spring.
  3. autowire by constructor – C’est presque similaire à autowire byType, la seule différence est que le constructeur est utilisé pour injecter la dépendance.
  4. autowire by autodetect – Si vous utilisez Spring 3.0 ou des versions antérieures, c’est l’une des options d’autowire disponibles. Cette option était utilisée pour autowire par constructeur ou par type, comme déterminé par le conteneur Spring. Comme nous avons déjà tant d’options, cette option est obsolète. Je ne couvrirai pas cette option dans ce tutoriel.
  5. @Autowired annotation – Nous pouvons utiliser l’annotation @Autowired Spring pour l’autocâblage des beans Spring. L’annotation @Autowired peut être appliquée sur des variables et des méthodes pour l’autocâblage par type. Nous pouvons également utiliser l’annotation @Autowired sur le constructeur pour l’autocâblage basé sur le constructeur de printemps. Pour que l’annotation @Autowired fonctionne, nous devons également activer la configuration basée sur les annotations dans le fichier de configuration des beans Spring. Cela peut être fait en utilisant l’élément context:annotation-config ou en définissant un bean de type org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.
  6. L’annotation @Qualifier – Cette annotation est utilisée pour éviter les conflits dans la correspondance des beans et nous devons fournir le nom du bean qui sera utilisé pour l’autocâblage. De cette façon, nous pouvons éviter les problèmes où plusieurs beans sont définis pour le même type. Cette annotation fonctionne généralement avec l’annotation @Autowired. Pour les constructeurs avec plusieurs arguments, nous pouvons utiliser cette annotation avec les noms d’arguments dans la méthode.

Par défaut, l’autocâblage des beans Spring est désactivé. La valeur par défaut de l’autocâblage des beans Spring est « par défaut », ce qui signifie qu’aucun autocâblage ne doit être effectué. La valeur d’autocâblage « no » a également le même comportement. Pour illustrer l’utilisation de l’autocâblage des beans Spring, créons un projet Spring Maven simple. Notre projet final ressemblera à l’image ci-dessous. Examinons chacune des options d’autocâblage une par une. Pour cela, nous créerons un bean Model et une classe de service où nous injecterons le bean Model.

Spring @Autowired Annotation – Dépendances Maven

Pour l’autocâblage Spring, nous n’avons pas besoin d’ajouter de dépendances supplémentaires. Notre fichier pom.xml contient les dépendances de base du framework Spring et ressemble à ce qui suit.

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

Printemps @Autowired Annotation – Modèle de Bean

Créons un simple Java Bean, nommé Employee. Ce bean aura une seule propriété avec des méthodes getter et setter. Nous initialiserons la valeur de cette propriété dans le fichier de configuration du bean 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;
	}
}

Printemps @Autowired Annotation – Classe de Service

Créons notre classe de service dans laquelle nous injecterons le bean Employee via l’autocâblage Spring.

package com.journaldev.spring.autowiring.service;

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

public class EmployeeService {

	private Employee employee;

	// Le constructeur est utilisé pour l'autocâblage par le constructeur
	public EmployeeService(Employee emp) {
		System.out.println("Autowiring by constructor used");
		this.employee = emp;
	}

	// Constructeur par défaut pour éviter l'exception BeanInstantiationException pour l'autocâblage
	// parNom ou parType
	public EmployeeService() {
		System.out.println("Default Constructor used");
	}

	// Utilisé pour l'autocâblage parNom et parType
	public void setEmployee(Employee emp) {
		this.employee = emp;
	}

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

Nous utiliserons la même classe de service pour effectuer l’autocâblage Spring par nom, par type et par constructeur. La méthode setter sera utilisée pour l’autocâblage Spring par nom et par type, tandis que l’injection basée sur le constructeur sera utilisée avec l’attribut d’autocâblage du constructeur. Lorsque nous utilisons l’autocâblage Spring par nom ou par type, le constructeur par défaut est utilisé. C’est pourquoi nous avons explicitement défini le constructeur par défaut pour le bean EmployeeService.

Spring @Autowired Annotation – Exemple d’autocâblage par type

Créons une classe séparée avec l’annotation Spring @Autowired pour l’autocâblage par type.

package com.journaldev.spring.autowiring.service;

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

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

public class EmployeeAutowiredByTypeService {

	// L'annotation @Autowired sur la variable/les setters est équivalente à autowire="byType"
	@Autowired
	private Employee employee;
	
	@Autowired
	public void setEmployee(Employee emp){
		this.employee=emp;
	}
	
	public Employee getEmployee(){
		return this.employee;
	}
}

Remarquez que j’ai annoté à la fois la variable Employee et sa méthode setter avec l’annotation Spring @Autowired, cependant une seule de ces annotations est suffisante pour l’autocâblage du bean Spring.

Printemps @Autowired Annotation et Exemple d’autocâblage de bean par constructeur avec @Qualifier

Créons une autre classe de service où nous utiliserons l’annotation @Autowired pour l’injection basée sur le constructeur. Nous verrons également l’utilisation de l’annotation @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;

	// L'annotation Autowired sur le constructeur est équivalente à autowire="constructor"
	@Autowired(required=false)
	public EmployeeAutowiredByConstructorService(@Qualifier("employee") Employee emp){
		this.employee=emp;
	}
	
	public Employee getEmployee() {
		return this.employee;
	}
}

Lorsque ce bean sera initialisé par le framework Spring, le bean portant le nom « employee » sera utilisé pour l’autocâblage. L’annotation @Autowired de Spring attend un argument « required » qui est un booléen avec une valeur par défaut de VRAI. Nous pouvons le définir comme « faux » afin que le framework Spring ne génère aucune exception si aucun bean approprié n’est trouvé pour l’autocâblage.

Annotation @Autowired – Fichier de Configuration des Beans

Le fichier de configuration des beans Spring est la partie principale de toute application Spring, voyons à quoi ressemble notre fichier de configuration des beans Spring, puis nous examinerons chaque partie en détail.

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

Les points importants concernant le fichier de configuration des beans Spring sont les suivants :

  • L’élément beans default-autowire est utilisé pour définir la méthode d’autocâblage par défaut. Ici, je définis la méthode d’autocâblage par défaut comme étant par nom.
  • L’élément beans default-autowire-candidates est utilisé pour fournir le motif des noms de beans pouvant être utilisés pour l’autocâblage. Pour simplifier, je permets à toutes les définitions de beans d’être éligibles pour l’autocâblage, cependant, nous pouvons définir un certain motif pour l’autocâblage. Par exemple, si nous voulons uniquement des définitions de beans DAO pour l’autocâblage, nous pouvons le spécifier comme default-autowire-candidates="*DAO".
  • autowire-candidate="false" est utilisé dans une définition de bean pour la rendre non éligible à l’autocâblage. C’est utile lorsque nous avons plusieurs définitions de beans pour un seul type et que nous ne voulons pas que certaines d’entre elles soient autocâblées. Par exemple, dans les configurations de beans Spring ci-dessus, le bean « employee1 » ne sera pas utilisé pour l’autocâblage.
  • L’attribut autowire byName, byType et constructor est auto-explicatif, il n’y a pas grand-chose à expliquer là-dessus. `
  • context:annotation-config` est utilisé pour activer la prise en charge de la configuration basée sur les annotations. Remarquez que les beans employeeAutowiredByTypeService et employeeAutowiredByConstructorService n’ont pas d’attributs autowire. `

Spring @Autowired` Annotation – Programme de Test `

`Maintenant que notre application Spring est prête avec tous les types d’autowiring Spring, écrivons un programme de test simple pour voir s’il fonctionne comme prévu ou non. `

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());
		
		`// impression du hashcode pour confirmer que tous les objets sont de types différents `
		System.out.println(serviceByName.hashCode()+"::"+serviceByType.hashCode()+"::"+serviceByConstructor.hashCode());
		
		`// Test des annotations @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();
	}
}

`Le programme est simple, nous créons simplement le contexte de l’application Spring et l’utilisons pour obtenir différents beans et afficher le nom de l’employé. Lorsque nous exécutons l’application ci-dessus, nous obtenons la sortie suivante.

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

Comme vous pouvez le voir, pour autowire par nom et par type, le constructeur par défaut sans arguments est utilisé pour initialiser le bean. Pour autowire par constructeur, le constructeur basé sur les paramètres est utilisé. À partir du code de hachage de toutes les variables, nous avons confirmé que tous les beans Spring sont des objets différents et ne font pas référence au même objet. Étant donné que nous avons retiré « employee1 » de la liste des beans éligibles pour l’autocâblage, il n’y avait aucune confusion dans la correspondance des beans. Si nous retirons autowire-candidate="false" de la définition de « employee1 », nous obtiendrons le message d’erreur suivant lors de l’exécution de la méthode principale ci-dessus.

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

C’est tout pour l’annotation Spring @Autowired et la fonctionnalité d’autocâblage Spring, veuillez télécharger le projet exemple à partir du lien ci-dessous et l’analyser pour en savoir plus.

Télécharger le projet Spring Bean Autowiring

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