Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Spring is based on the constructor's dependency injection


May 14, 2021 Spring


Table of contents


Spring is based on the constructor's dependency injection

When a container calls a class constructor with a set of parameters, the constructor-based DI is complete, with each argument representing a dependency on the other classes.

Next, we'll look at examples to understand Spring's constructor-based dependency injection.

Example:

The following example shows a Class TextEditor that can only be used for constructor injection to implement dependency injection.

Let's work properly with eclipse IDE and follow these steps to create a Spring application.

Steps Describe
1 Create a project called SpringExample and create a package com.tutorialspoint under the src folder in the project you create.
2 Use the Add External JARs option to add the required Spring library, as explained by Spring Hello World Example Chapter.
3 Create Java-like TextEditor, SpellChecker, and MainApp under the com.tutorialspoint package.
4 Create Beans profile Beans under the src .xml.
5 The final step is to create the contents of all Java files and bean profiles and run the application as follows.

This is the contents .java TextEditor file:

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

Here's what's in another class-dependent .java SpellChecker:

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

Here's what .java MainApp files are:

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

Here's .xml profile Beans, which has a constructor-injected configuration:

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

When you're done creating the source and bean profiles, let's start running the application. If your application runs well, the following message will be output:

Inside SpellChecker constructor.
Inside TextEditor constructor.
Inside checkSpelling.

Constructor argument parsing:

Note: In the example above, the file that relies on the spellChecker .java be injected into the TextEditor .java file.

This is called dependency injection.

If there is more than one argument, there may be ambiguity when the argument is passed to the constructor. To solve this problem, the order in which the constructor's arguments are in the bean definition is the order in which they are provided to the appropriate constructor.

Consider the following classes:

package x.y;
public class Foo {
   public Foo(Bar bar, Baz baz) {
      // ...
   }
}

The following profiles worked well:

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

Let's check again the different types of locations we pass to the constructor. Consider the following classes:

package x.y;
public class Foo {
   public Foo(int year, String name) {
      // ...
   }
}

If you type specify the type of constructor argument using the type property, the container can also use a type that matches the simple type. For example:

<beans>

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

</beans>

Last but not only the best way to pass constructor arguments, use index property to explicitly specify the index of constructor parameters. Here's an example based on index 0, as follows:

<beans>

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

</beans>

Finally, if you want to pass a reference to an object, you need to use the ref property of the tag, and if you want to pass the value directly, you should use the value property shown above.