Spring DI- Constructor Injection with XML Metadata configuration

In Constructor injection, spring container invokes a constructor or a static factory method with the number of the argument. Where each argument represents a dependency. An argument to static factory method or constructor is similar.
If no potential ambiguity exists in the constructor arguments of a bean definition, then the order in which the constructor arguments are defined in a bean definition is the order in which those arguments are supplied to the appropriate
constructor when the bean is being instantiated.

Constructor / Factory method argument resolution: There could be ambiguity in the argument list to constructor or factory method.
Example: Address class has properties as

     flatNo(String type) ,
     bldgNo(String type),
     streetNo(String type),
     city (int type),
     pincode (int type)

Constructor for contact class has the properties in order of(flatNo, bldgNo, streetNo, city, pincode) OR (String, String, String, String, int)

Constructor of Address class:

     public Address(String flatNo, String bldgNo, String streetNo, String city,int pincode) {
       super();
       this.flatNo = flatNo;
       this.bldgNo = bldgNo;
       this.streetNo = streetNo;
       this.city = city;
       this.pincode = pincode;
  }

    <bean id="companyWithConstInjectionArg">
      <constructor-arg  value="276002"></constructor-arg>
      <constructor-arg  value="360"></constructor-arg>
      <constructor-arg  value="My City"></constructor-arg>
      <constructor-arg  value="My Street"></constructor-arg>
      <constructor-arg  value="C2"></constructor-arg>
    </bean>

Here spring container could not resolve matching constructor. A container cannot identify which one should be treated as int and which one should be treated as String.
To avoid this kind of ambiguity index/type/name matching could be used.

Type Matching: Type(String/int) can be used to avoid ambiguity. Like in the previous example we can use type like String or int to match the argument type.
Example :

 <bean id="address" >
  <constructor-arg type="int" value="276044"></constructor-arg>          -- line 1
  <constructor-arg type="java.lang.String" value="360"></constructor-arg>         -- line 2
  <constructor-arg type="java.lang.String" value="C2"></constructor-arg>                -- line 3
  <constructor-arg type="java.lang.String" value="My Street"></constructor-arg>        -- line 4
  <constructor-arg type="java.lang.String" value="My City"></constructor-arg>        -- line 5
 </bean>

In the above example, a spring container will identify the sequence of argument the same as they are defined here and type will help the container to avoid ambiguity.
A sequence of argument in constructor would be line 2-3-4-5-1

Constructor argument sequence(Explicit): There might be the case when sequence of the argument is not the same in the constructor as it is defined in XML. To define the sequence of the argument explicitly, the index attribute could be used.

Example :

 <bean id="address" >
  <constructor-arg type="int" value="276044"></constructor-arg>          -- line 1
  <constructor-arg type="java.lang.String" value="My Street"></constructor-arg>        -- line 2
  <constructor-arg type="java.lang.String" value="My City"></constructor-arg>        -- line 3
  <constructor-arg type="java.lang.String" value="360" index ="0"></constructor-arg>     -- line 4
  <constructor-arg type="java.lang.String" value="C2" index ="1"></constructor-arg>      -- line 5
 </bean>

Note*: Index is 0 based.
Note*: Here index for two arguments is provided while the index for other 3 other args are not defined in that case container will take a sequence as it is defined here.
The sequence of the argument in the constructor should be line 4-5-2-3-1

Constructor argument name: Introduced in Spring 3.0. To resolve the argument ambiguity now the name of the constructor argument could also be used.

 <bean id="address" >
  <constructor-arg type="int" value="276044"></constructor-arg>                               -- line 1
  <constructor-arg type="java.lang.String" value="My City"></constructor-arg>                        -- line 2
  <constructor-arg type="java.lang.String" name ="street" value="My Street"></constructor-arg>        -- line 3
  <constructor-arg type="java.lang.String" value="360" index ="0"></constructor-arg>                     -- line 4
  <constructor-arg type="java.lang.String" value="C2" index ="1"></constructor-arg>                      -- line 5
 </bean>

Here the name of the argument is mentioned as “street” hence that will be treated as an argument for street field. For others, the sequence will be treated as it defined here.
The sequence of argument in constructor would be line 3-2-4-5-1

Note*: To make it work @ConstructorProperties() needs to be used to define the name of the property.

@ConstructorProperties({"flatNo", "bldgNo","streetNo","city","pincode"})
 public Address(String flatNo, String bldgNo, String streetNo, String city,int pincode) {
  super();
  this.flatNo = flatNo;
  this.bldgNo = bldgNo;
  this.streetNo = streetNo;
  this.city = city;
  this.pincode = pincode;
 }

All the above things can be done via a static factory method instead of the constructor. In that case name of the factory method in the class needs to be mentioned via “factory-method” tag.

Example: Address class has a static factory method that creates Object of the address class and does some operation on it.

 public static Address createInstance(String flatNo, String bldgNo, String streetNo, String city, int pincode){
  Address a1 = new Address();
  a1.setflatNo(add);
  a1.setbldgNo(com);
  a1.setstreetNo(name);
  a1.setCity(city);
  a1.setPincode(pincode);
  return a1;
 }

Now we can use constructor injection, but not static factory method will be invoked.

 <bean id="address" factory-method="createInstance">
  <constructor-arg type="int" value="276044"></constructor-arg>
  <constructor-arg type="java.lang.String" value="360"></constructor-arg>
  <constructor-arg type="java.lang.String" value="C2"></constructor-arg>
  <constructor-arg type="java.lang.String" value="My Street"></constructor-arg>
  <constructor-arg type="java.lang.String" value="My City"></constructor-arg>
 </bean>

 

Leave A Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.