Injection de dépendances basée sur le constructeur

La DI basée sur un constructeur est effectuée lorsque le conteneur appelle un constructeur de classe avec un certain nombre d'arguments, chacun représentant une dépendance à l'autre classe.

Exemple

L'exemple suivant montre une classe TextEditor qui ne peut être injectée de dépendances qu'avec l'injection de constructeur.

Laissez-nous mettre en place un IDE Eclipse fonctionnel et suivez les étapes suivantes pour créer une application Spring -

Pas La description
1 Créez un projet avec un nom SpringExample et créez un package com.tutorialspoint sous lesrc dossier dans le projet créé.
2 Ajoutez les bibliothèques Spring requises à l'aide de l' option Ajouter des JAR externes , comme expliqué dans le chapitre Exemple de Spring Hello World .
3 Créez les classes Java TextEditor , SpellChecker et MainApp sous le package com.tutorialspoint .
4 Créez le fichier de configuration Beans Beans.xml sous lesrc dossier.
5 La dernière étape consiste à créer le contenu de tous les fichiers Java et le fichier de configuration Bean et à exécuter l'application comme expliqué ci-dessous.

Voici le contenu de TextEditor.java fichier -

package com.tutorialspoint;

public class TextEditor {
   private SpellChecker spellChecker;

   public TextEditor(SpellChecker spellChecker) {
      System.out.println("Inside TextEditor constructor." );
      this.spellChecker = spellChecker;
   }
   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

Voici le contenu d'un autre fichier de classe dépendant SpellChecker.java

package com.tutorialspoint;

public class SpellChecker {
   public SpellChecker(){
      System.out.println("Inside SpellChecker constructor." );
   }
   public void checkSpelling() {
      System.out.println("Inside checkSpelling." );
   }
}

Voici le contenu de la MainApp.java fichier

package com.tutorialspoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

      TextEditor te = (TextEditor) context.getBean("textEditor");
      te.spellCheck();
   }
}

Voici le fichier de configuration Beans.xml qui a une configuration pour l'injection basée sur le constructeur -

<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <!-- Definition for textEditor bean -->
   <bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
      <constructor-arg ref = "spellChecker"/>
   </bean>

   <!-- Definition for spellChecker bean -->
   <bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"></bean>

</beans>

Une fois que vous avez terminé de créer les fichiers de configuration source et bean, laissez-nous exécuter l'application. Si tout va bien avec votre application, elle imprimera le message suivant -

Inside SpellChecker constructor.
Inside TextEditor constructor.
Inside checkSpelling.

Résolution des arguments du constructeur

Il peut y avoir une ambiguïté lors de la transmission des arguments au constructeur, au cas où il y aurait plus d'un paramètre. Pour résoudre cette ambiguïté, l'ordre dans lequel les arguments du constructeur sont définis dans une définition de bean est l'ordre dans lequel ces arguments sont fournis au constructeur approprié. Considérez la classe suivante -

package x.y;

public class Foo {
   public Foo(Bar bar, Baz baz) {
      // ...
   }
}

La configuration suivante fonctionne correctement -

<beans>
   <bean id = "foo" class = "x.y.Foo">
      <constructor-arg ref = "bar"/>
      <constructor-arg ref = "baz"/>
   </bean>

   <bean id = "bar" class = "x.y.Bar"/>
   <bean id = "baz" class = "x.y.Baz"/>
</beans>

Vérifions un autre cas où nous passons différents types au constructeur. Considérez la classe suivante -

package x.y;

public class Foo {
   public Foo(int year, String name) {
      // ...
   }
}

Le conteneur peut également utiliser la correspondance de type avec des types simples, si vous spécifiez explicitement le type de l'argument constructeur à l'aide de l'attribut type. Par exemple -

<beans>

   <bean id = "exampleBean" class = "examples.ExampleBean">
      <constructor-arg type = "int" value = "2001"/>
      <constructor-arg type = "java.lang.String" value = "Zara"/>
   </bean>

</beans>

Enfin, la meilleure façon de transmettre des arguments de constructeur est d'utiliser l'attribut index pour spécifier explicitement l'index des arguments de constructeur. Ici, l'indice est basé sur 0. Par exemple -

<beans>

   <bean id = "exampleBean" class = "examples.ExampleBean">
      <constructor-arg index = "0" value = "2001"/>
      <constructor-arg index = "1" value = "Zara"/>
   </bean>

</beans>

Une dernière remarque, dans le cas où vous passez une référence à un objet, vous devez utiliser ref attribut de la balise <constructor-arg> et si vous passez une valeur directement, vous devez utiliser value attribut comme indiqué ci-dessus.