14 - Spring Beans AutoWiring

14.1 Overview

We have seen been developed several examples in earlier chapters on dependency injection. Usually we provide bean configuration details in the spring bean configuration file and specify the beans that will be injected in other beans using ref attribute or using an innet bean.

 Spring framework provides an  autowiring feature with which we need not to use ref attribute and provide bean references explicitly instead we can configure the auto-wire mode and spring container automatically wires the beans.

We can configure auto wire mode using “autowire” attribute (refer below snippet).

    <bean id="bean_id" class="bean_class" autowire="default | byname | byType | constructor | autodetect " />

Following are the different autowiring modes supported by Spring.

  • Default or no
  • byname
  • byType
  • constructor
  • autodetect

With spring 2.5 onwards , we can use following annotations as well

  • @Autowired
  • @Qualifier

Note:

  • Explicit dependencies using < property> and <constructor-arg> settings always override the auto wiring.
  • Currently not possible to autowire simple properties such as String, primitive types, collections etc.

14.2 Auto Wiring Modes

14.2.1  no

This is default setting and there will be no auto wiring. We need to explicitly wires the bean using ref attribute and this is what we have done in earlier chapters.

Default value of autowire attribute of bean is “default” which means no autowiring will be performed. Setting  autowire  attribute with value “no” will have the same behavior.

Below three statements are equivalent

<bean id="bean_id" class="bean_class" autowire="default"/>
<bean id="bean_id" class="bean_class" autowire="no "/>
<bean id="bean_id" class="bean_class" />

14.2.2  byName

In this mode autowiring performs based on the name of property. Container inspects the spring configuration file and looks for the bean having name or id attribute same as the property name. This mode is applied on Setter methods.

Since the we cannot have a multiple beans in configuration files having same value of id attribute, thus there is no chance having a multiple match for a property. In case bean with given name or id does not found , that property will remain unset.

Refer below snippet on how to configure byName auto wiring mode

      <bean id="bean_id" class="bean_class" autowire="byName"/>

For example we have a bean definition which has byName auto wiring mode and it contains a property with name “master” (and will have corresponding setMaster() method), then container will look for a bean having name or id attribute set to ‘master’ and will pass that bean in corresponding setter method.

In case we there are multiple properties in a bean and we just want some of them to be auto-wired then we can add property tags for the ones we do not need auto-wire feature

14.2.2.1 Example

 Consider a scenario where each Room will be allocated to one student and will have a unique room number. We will wire the student object in to Room using byName auto wire mode and the room number using property tag.

  1. Student.java
public class Student {
       private String name ;
       public String getName() {
              return name;
       }
       public void setName(String name) {
              this.name = name;
       }
}
  1. Room.java
public class Room
{
       private String roomNumber;
       private Student allotedTo;
       public String getRoomNumber() {
              return roomNumber;
       }
       public void setRoomNumber(String roomNumber) {
              this.roomNumber = roomNumber;
       }
       public Student getAllotedTo() {
              return allotedTo;
       }
       public void setAllotedTo(Student allotedTo) {
              this.allotedTo = allotedTo;
       }
       @Override
       public String toString() {
              String name= "";
              if(allotedTo!=null)
              {
                     name= allotedTo.getName();
              }
              return "Room [roomNumber=" + roomNumber + ", allotedTo=" + name      + "]";
       }
}
  1. Beans.xml file to configure beans using byName auto wire mode
<?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">
        <bean id="allotedTo" class="Student">
              <property name="name" value="Student A" />
        </bean>      
        <bean id="room" class="Room" autowire="byName">
              <property name="roomNumber" value="R-101" />
       </bean>      
</beans>
  1. TestByNameAutowire.java class to test byName auto wiring mode.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestByNameAutoWire {
    public static void main(String[] args) {
       ApplicationContext context =
       new ClassPathXmlApplicationContext("beans.xml");
       Room room = (Room)context.getBean("room");
       System.out.println(room);             
       }
}
  1. Run TestByNameAutowire – you will see below output

14.2.3  byType

In this mode autowiring performs based on the class type of property. Container inspects the spring configuration file and looks for the bean of same class type. This mode is applied on Setter methods.

  1. If no bean with class type found than property will remain unset
  2. If one bean with class type found then property will be set
  3. If there are multiple beans found with class type in beans configuration found, then exception will be thrown.

Refer below snippet on how to configure byType auto wiring mode

               <bean id="bean_id" class="bean_class" autowire="byType"/>

For example we have a bean definition which has byType auto wiring mode and it contains a property with name “master” of type ClassA then container will look for a bean of type ClassA  and will pass that bean in corresponding setter method.

In case we there are multiple properties in a bean and we just want some of them to be auto-wired then we can add property tags for the ones we do not need auto-wire feature

14.2.3.1 Example

Consider a scenario where each Room will be allocated to one student and will have a unique room number. We will wire the student object in to Room using byType auto wire mode and the room number using property tag.

  1. Student.java
public class Student {
       private String name ;
       public String getName() {
              return name;
       }
       public void setName(String name) {
              this.name = name;
       } 
}
  1. Room.java
public class Room{
       private String roomNumber;
       private Student allotedTo;
       public String getRoomNumber() {
              return roomNumber;
       }
       public void setRoomNumber(String roomNumber) {
              this.roomNumber = roomNumber;
       }
       public Student getAllotedTo() {
              return allotedTo;
       }
       public void setAllotedTo(Student allotedTo) {
              this.allotedTo = allotedTo;
       }
       @Override
       public String toString() {
              String name= "";
              if(allotedTo!=null)
              {
                     name= allotedTo.getName();
              }
              return "Room [roomNumber=" + roomNumber + ", allotedTo=" + name      + "]";
       }
}
  1. Beans.xml file to configure beans using byType auto wire mode
<?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">
        <bean id="studentA" class="Student">
              <property name="name" value="Student A" />
        </bean>      
        <bean id="room" class="Room" autowire="byType">
              <property name="roomNumber" value="R-101" />
       </bean>      
</beans>
  1. TestByTypeAutowire.java class to test byType auto wiring mode.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestByTypeAutoWire {
    public static void main(String[] args) {
       ApplicationContext context =
       new ClassPathXmlApplicationContext("beans.xml");
       Room room = (Room)context.getBean("room");
       System.out.println(room);             
   }
}
  1. Run TestByTypeAutowire – you will see below output

14.2.3.2

Add one more bean of type Student in beans.xml and re-run the TestByTypeAutowire program like:

<bean id="studentB" class="Student">
       <property name="name" value="Student B" />
</bean>

You will get an exception because beans.xml will now have multiple beans matching for class Student

14.2.4  constructor

Constructor auto wiring mode is similar to byType with the difference is that this mode is applied on constructor arguments where as byType applies on setter methods of properties.

  1. If no bean with class type found in beans configuration found, then exception will be thrown.
  2. If one bean with class type found then property will be set
  3. If there are multiple beans found with class type in beans configuration found, then exception will be thrown if default constructor is not defined else default constructor will be used.

Refer below snippet on how to configure constructor auto wiring mode

      <bean id="bean_id" class="bean_class" autowire="constructor"/>

14.2.4.1 Constructor Ambiguity Resolution

We can define multiple constructors in a bean and therefore there are high chances of ambiguity with constructor auto wiring.

  1. If there are multiple beans found with class type in beans configuration found,
    •  then exception will be thrown if default constructor is not defined
    • default constructor will be used if defined
  2. if there are multiple constructors and dependency of multiple constructors are satisfied, then container can call any one of them. For example Room class has two constructor (one takes Student object and another takes Floor object). In beans if there are exactly one bean defined for each type (one for Floor and one for Student) than any of the constructor can be invoked

14.2.4.2 Example

Consider a scenario where each Room will be allocated to one student and will have a unique room number. We will wire the student object in to Room using constructor auto wire mode and the room number using property tag.

  1. Student.java
public class Student {
       private String name ;
       public String getName() {
              return name;
       }
       public void setName(String name) {
              this.name = name;
       }
}
  1. Room.java
public class Room
{
       private String roomNumber;
       private Student allotedTo;
       public String getRoomNumber() {
              return roomNumber;
       }
       public void setRoomNumber(String roomNumber) {
              this.roomNumber = roomNumber;
       }
       public Room(Student allotedTo) {
              this.allotedTo = allotedTo;
       }      
       @Override
       public String toString() {
              String name= "";
              if(allotedTo!=null)
              {
                     name= allotedTo.getName();
              }
              return "Room [roomNumber=" + roomNumber + ", allotedTo=" + name            + "]";
       }
}
  1. Beans.xml file to configure beans using constructor auto wire mode
<?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">
        <bean id="studentA" class="Student">
              <property name="name" value="Student A" />
        </bean>      
        <bean id="room" class="Room" autowire="constructor">
              <property name="roomNumber" value="R-101" />
        </bean>      
</beans>
  1. TestConstructorAutowire.java class to test constructor auto wiring mode.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestConstructorAutoWire {
   public static void main(String[] args) {
       ApplicationContext context =
       new ClassPathXmlApplicationContext("beans.xml");
       Room room = (Room)context.getBean("room");
       System.out.println(room);             
   }
}
  1. Run TestConstructorAutowire – you will see below output

14.2.4.2

Add one more bean of type Student in beans.xml and re-run the TestConstructorAutowire program like

<bean id="studentB" class="Student">
       <property name="name" value="Student B" />
</bean>

You will get an exception because beans.xml will now have multiple beans matching for class Student

14.2.4.3

Add default constructor in Room.java  re-run the TestConstructorAutowire program. This time instead of exception, default constructor will be invoked.

public Room()
{
     System.out.println("Default Constructor Called ");
}

14.2.5 autodetect

This auto wring mode  resolves auto wiring either by constructor or byType, as determined by Spring container. If constructor mode does not satisfies dependency then byType mode is used

14.3 @Autowired and @Qualifier annotation

With Spring 2.5 onwards, we can use annotations for auto wiring instead of configuring it in beans configuration files. There is a separate chapters on annotations and we will discuss these annotations in those chapters.

14.4 Configure Default Autowiring at a global level

We can define auto wiring modes in the beans tag so it will be applicable on all the beans defined. We still can override the mode at a bean level using the autowire attribute at bean level.

 “default-autowire”  attribute can be used at a beans level  to define the default autowiring mode.

Like us on Facebook