Tuesday, May 13, 2014

What is Autowiring in Spring Framework?

What is autowiring?
The Spring container can autowire relationships between collaborating beans without using <constructor-arg> and <property> elements which helps cut down on the amount of XML configuration you write for a big Spring based application.

There are TWO ways to provide autowiring to your beans
1)       Through XML based configuration file (applicationContext.xml)
2)       With Annotations in beans directly.(Spring 2.5 and above)


Lets see how we can use autowiring through xml configuration file.

 Before that lets find out what are different type of autowiring is possible in Spring.


Mode
Description
No
This is default setting which means no autowiring and you should use explicit bean reference for wiring. You have nothing to do special for this wiring.
Autowiring by property name. Spring container looks at the properties of the beans on which autowire attribute is set to byName in the XML configuration file. It then tries to match and wire its properties with the beans defined by the same names in the configuration file.
Autowiring by property datatype. Spring container looks at the properties of the beans on which autowire attribute is set to byType in the XML configuration file. It then tries to match and wire a property if its typematches with exactly one of the beans name in configuration file. If more than one such beans exists, a fatal exception is thrown.
Similar to byType, but type applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised.
autodetect
Spring first tries to wire using autowire by constructor, if it does not work, Spring tries to autowire by byType.

You should consider the limitations and disadvantages of autowiring before using them.

Limitations
Description
Overriding possibility
You can still specify dependencies using <constructor-arg> and <property> settings which will always override autowiring.
Primitive data types
You cannot autowire so-called simple properties such as primitives, Strings, and Classes.
Confusing nature
Autowiring is less exact than explicit wiring, so if possible prefer using explicit wiring.


Lets discuss those 5 types of auto wiring in detail with examples.

1) Default “No”
This is the default mode, you need to wire your bean via ‘ref’ attribute.
<bean id="customer" class="com.common.Customer">
     <property name="person" ref="person" /> 

</bean>
<bean id="person" class="com.common.Person" />

2) Auto-Wiring ‘byName’
Auto-wire a bean by property name.  If the name of a bean is same as the name of other bean property, auto wire it. For example, if a “customer” bean exposes an “address” property, Spring will find the “address” bean in current container and wire it automatically. And if no matching found, just do nothing.
<bean id="customer" class="com.common.Customer" autowire="byName" /> 

<bean id="address" class="com.common.Address" >

  <property name="fulladdress" value="Vasant Vihar, Mumbai" />

</bean>
//Customer bean

package com.common;
public class Customer { 

   private Address address;

   //...

}
//Address bean

package com.common; 
public class Address{

        private String fulladdress;

        //...

}
Normally, you wire the bean explicitly (without autowiring), via ref attribute like this :
        <bean id="customer" class="com.common.Customer" >

               <property name="address" ref="address" />

        </bean>
        <bean id="address" class="com.common.Address" >

          <property name="fulladdress" value="Vasant Vihar, Mumbai" />

        </bean>
With autowire by name enabled, you do not need to declare the property tag anymore. As long as the “address” bean is same name as the property of “customer” bean, which is “address”, Spring will wire it automatically.
<bean id="customer" class="com.common.Customer" autowire="byName" /> 

<bean id="address" class="com.common.Address" >

  <property name="fulladdress" value="Vasant Vihar, Mumbai" />

</bean>
Output
Customer [address=Address [fulladdress=Vasant Vihar, Mumbai]]

See another example, this time, the wiring will failed, caused the bean “addressABC” is not match the property name of bean “customer”.
<bean id="customer" class="com.common.Customer" autowire="byName" />

<bean id="addressABC" class="com.common.Address" >

   <property name="fulladdress" value="Vasant Vihar, Mumbai" />

</bean>
Output
Customer [address=null]


3) Auto-Wiring ‘byType’
Auto-wire a bean by data type. If data type of a bean is compatible with the data type of other bean property, auto wire it.
For example, a “person” bean exposes a property with data type of “ability” class, Spring will find the bean with same data type of class “ability” and wire it automatically. And if no matching found, just do nothing.

package com.common;

public class Person {

      private Ability ability;

//...

}

package com.common;

public class Ability{
        private String skill;

        //...

}
Normally, you wire the bean explicitly: (without autowiring), via ref attribute like this :
<bean id="person" class="com.common.Person">

  <property name="ability" ref="invisible" />

</bean> 

<bean id="invisible" class="com.common.Ability" >

   <property name="skill" value="Invisible" />

</bean>
Output
Person [ability=Ability [skill=Invisible]]
With autowire by type enabled, you can leave the ability property unset. Spring will find the same data type and wire it automatcailly.
<bean id="person" class="com.common.Person" autowire="byType" />

<bean id="invisible" class="com.common.Ability" >

   <property name="skill" value="Invisible" />

</bean>
Output
Person [ability=Ability [skill=Invisible]]
Wait, what if you have two beans with same data type of class “ability”?
<bean id="person" class="com.common.Person" autowire="byType" />

<bean id="steal" class="com.common.Ability" >

   <property name="skill" value="Steal" />

</bean> 

<bean id="invisible" class="com.common.Ability" > 

   <property name="skill" value="Invisible" />

</bean>
Output
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: 
...
No unique bean of type [com.common.Ability] is defined: 
expected single matching bean but found 2: [steal, invisible]; nested exception is 
org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No unique bean of type [com.common.Ability] is defined: 
expected single matching bean but found 2: [steal, invisible]
In this case, you will hits the UnsatisfiedDependencyException error message.

4) Auto-Wiring ‘constructor’

Auto-wire a bean by property data type in constructor argument. It means, if data type of a bean is same as the data type of other bean constructor argument, auto wire it. 

<bean id="developer" class="com.common.Developer" autowire="constructor" />

<bean id="language" class="com.common.Language" >

   <property name="name" value="Java" />

</bean>

package com.common;

public class Developer {

 private Language language;



  //autowire by constructor
public Developer(Language language) {

this.language = language;

}

//...

}


package com.common;
public class Language {

 private String name;

//...

}
Normally, you wire the bean via constructor like this (without autowiring).

Normally, you wire the bean via constructor like this :
<bean id="developer" class="com.common.Developer">

       <constructor-arg>

              <ref bean="language" />

       </constructor-arg>

</bean>

<bean id="language" class="com.common.Language" >

      <property name="name" value="Java" />

</bean>
With autowire by constructor enabled, you can leave the constructor property unset. Spring will find the compatible data type and wire it automatically.
<bean id="developer" class="com.common.Developer" autowire="constructor" />

<bean id="language" class="com.common.Language" >

   <property name="name" value="Java" />

</bean>

5) Auto-Wiring ‘autodetect’
If a default constructor is found, uses “constructor”; Otherwise, uses “byType” please refer above example for more reference how constructor or byType autowiring is used.


Conclusion
In my view, Spring ‘auto-wiring’ make development faster with great costs – it added complexity for the entire bean configuration file, and you don’t even know which bean will auto wired in which bean.
In practice, I rather wire it manually, it is always clean and work perfectly, or better uses @Autowired annotation, which is more flexible and recommended.


Now let’s see some examples and details about Autowiring through annotations.
In Spring, you can use @Autowired annotation to auto wire bean on the setter method, constructor or a field. Moreover, it can autowired property in a particular bean.

The @Autowired annotation is auto wire the bean by matching data type.
Before you start using annotation or @autowired you need to register AutowiredAnnotationBeanPostProcessor and you can do it in two ways.
1. Include <context:annotation-config />
Add Spring context and <context:annotation-config /> in bean configuration file.
e.g. <beans 

//...

xmlns:context=http://www.springframework.org/schema/context

//...

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd">

//... 

      <context:annotation-config />

//...

</beans>
2. Include AutowiredAnnotationBeanPostProcessor
Include ‘AutowiredAnnotationBeanPostProcessor’ directly in bean configuration file.
e.g. <beans 

//...

xmlns:context=http://www.springframework.org/schema/context

//...

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd">

//... 

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
//...

</beans>

@Autowired Examples

Now, you can autowired bean via @Autowired, and it can be applied on setter method, constructor or a field.
1. @Autowired setter method
package com.common;

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

public class Customer {

        private Person person;

        private int type;

        private String action;

        //getter and setter method 
        @Autowired

        public void setPerson(Person person) {

              this.person = person;

        }

}
2. @Autowired construtor
package com.common;

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



public class Customer {

private Person person;

private int type;

private String action;
//getter and setter methods

@Autowired

public Customer(Person person) {

this.person = person;

 }

}
3. @Autowired field
package com.common;

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

public class Customer{
        @Autowired

        private Person person;

        private int type; 

        private String action;
//getter and setter methods

}
The above example will autowired ‘PersonBean’ into Customer’s person property.
package com.common;

import org.springframework.context.ApplicationContext

import org.springframework.context.support.ClassPathXmlApplicationContext;

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



  Customer cust = (Customer)context.getBean("CustomerBean");

  System.out.println(cust);

 }

}

Hope this small article help to understand the autowiring concepts in Spring. Please leave your comment/suggestion in comments I would appreciate and do any changes if required.