Wednesday, January 29, 2014

Spring beans autowiring concepts

In spring framework, setting bean dependencies in configuration files is a good practice to follow, but the spring container is also able to autowire relationships between collaborating beans. This means that it is possible to automatically let Spring resolve collaborators (other beans) for your bean by inspecting the contents of the BeanFactory.Autowiring is specified per bean and can thus be enabled for some beans, while other beans will not be autowired.
Spring autowiring modes
Spring autowiring modes

The autowiring functionality has five modes. These are ‘no’, ‘byName’, ‘byType’, ‘constructor’, and ‘autodetect’. The default mode is “no” i.e. by default autowiring is turned off.
Sections in this post:

Various autowiring modes used in bean configuration file
Using autowiring with @Autowired annotations
Using @Qualifier in case of conflict
Making autowiring error safe using required=false
Excluding a bean from being available for autowiring

Various autowiring modes used in bean configuration file

As shown in picture above, there are five auto wiring modes. Lets discuss them one by one.
  • no: This option is default for spring framework and it means that autowiring is OFF. You have to explicitly set the dependencies using tags in bean definitions.
  • byName: This option enables the dependency injection based on bean names. When autowiring a property in bean, property name is used for searching a matching bean definition in configuration file. If such bean is found, it is injected in property. If no such bean is found, a error is raised.
  • byType: This option enables the dependency injection based on bean types. When autowiring a property in bean, property’s class type is used for searching a matching bean definition in configuration file. If such bean is found, it is injected in property. If no such bean is found, a error is raised.
  • constructor: Autowiring by constructor is similar to byType, but applies to constructor arguments. In autowire enabled bean, it will look for class type of constructor arguments, and then do a autowire by type on all constructor arguments. Please note that if there isn’t exactly one bean of the constructor argument type in the container, a fatal error is raised.
  • autodetect: Autowiring by autodetect uses either of two modes i.e. constructor or byType modes. First it will try to look for valid constructor with arguments, If found the constructor mode is chosen. If there is no constructor defined in bean, or explicit default no-args constructor is present, the autowire byType mode is chosen.

Using autowiring with @Autowired annotations

Apart from the autowiring modes provided in bean configuration file, autowiring can be specified in bean classes also using @Autowired annotation. To use @Autowired annotation in bean classes, you must first enable the annotation in spring application using below configuration.
Same can be acheived using ‘AutowiredAnnotationBeanPostProcessor’ bean definition in configuration file.
Now, when annotation configuration has been enables, you are free to autowire bean dependencies using @Autowired, the way you like. This is done by three ways:
1) @Autowired on properties
When @Autowired is used on properties, it is equivalent to autowiring by ‘byType’ in configuration file.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class EmployeeBean
{
    @Autowired
    private DepartmentBean departmentBean;
      
    public DepartmentBean getDepartmentBean() {
        return departmentBean;
    }
    public void setDepartmentBean(DepartmentBean departmentBean) {
        this.departmentBean = departmentBean;
    }
    //More code
}
2) @Autowired on property setters
When @Autowired is used on setters, it is also equivalent to autowiring by ‘byType’ in configuration file.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class EmployeeBean
{
    private DepartmentBean departmentBean;
      
    public DepartmentBean getDepartmentBean() {
        return departmentBean;
    }
     
    @Autowired
    public void setDepartmentBean(DepartmentBean departmentBean) {
        this.departmentBean = departmentBean;
    }
    //More code
}
3) @Autowired on constructors
When @Autowired is used on bean’s constructor, it is also equivalent to autowiring by ‘constructor’ in configuration file.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.howtodoinjava.autowire.constructor;
  
public class EmployeeBean
{
    @Autowired
    public EmployeeBean(DepartmentBean departmentBean)
    {
        this.departmentBean = departmentBean;
    }
     
    private DepartmentBean departmentBean;
  
    public DepartmentBean getDepartmentBean() {
        return departmentBean;
    }
    public void setDepartmentBean(DepartmentBean departmentBean) {
        this.departmentBean = departmentBean;
    }
    //More code
}

Using @Qualifier in case of conflict

As we learned that if we are using autowiring in ‘byType’ mode and dependencies are looked for property class types. If no such type is found, an error is thrown. But, what if there are two or more beans for same class type.
In this case spring will not be able to choose correct bean to inject into property, and you will need to help the container using qualifiers.
To resolve a specific bean using qualifier, we need to use @Qualifier annotation along with @Autowired annotation and pass the bean name in annotation parameter. Take a look below for example:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class EmployeeBean
{
    @Autowired
    @Qualifier("finance")
    private DepartmentBean departmentBean;
      
    public DepartmentBean getDepartmentBean() {
        return departmentBean;
    }
    public void setDepartmentBean(DepartmentBean departmentBean) {
        this.departmentBean = departmentBean;
    }
    //More code
}
where duplicate beans are as below:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
xml version="1.0" encoding="UTF-8"?>
<beans>
    <context:annotation-config />
      
    <bean id="employee" class="com.howtodoinjava.autowire.constructor.EmployeeBean" autowire="constructor">
        <property name="fullName" value="Lokesh Gupta"/>
    </bean>
    
    <bean id="humanResource" class="com.howtodoinjava.autowire.constructor.DepartmentBean" >
        <property name="name" value="Human Resource" />
    </bean>
     
    
     <bean id="finance"      class="com.howtodoinjava.autowire.constructor.DepartmentBean" >
        <property name="name" value="Finance" />
    </bean>
</beans>

Making autowiring error safe using required=false

Even if you have used utmost care in autowiring bean dependencies, still you may find strange lookup failures. So, solve this issue, you will need to make autowiring optional so that if no dependency is found, application should not throw any exception and autowiring should simpy be ignored.
This can be done in two ways:
1)If you want to make specific bean autowiring non-mandatory for a specific bean property, use required=”false” attribute in @Autowired annoration
?
1
2
3
@Autowired (required=false)
@Qualifier ("finance")
private DepartmentBean departmentBean;
2) If you want to apply optional autowiring at global level i.e. for all properties in all beans; use below configuration setting.
?
1
2
3
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
    <property name="requiredParameterValue" value="false" />
</bean>

Excluding a bean from being available for autowiring

By default, autowiring scan and matches all bean definitions in scope. If you want to exclude some bean definitions so that they can not be injected through autowiring mode, you can do this using ‘autowire-candidate’ set to false.
1) Using ‘autowire-candidate‘ as false totally exclude a bean from being an autowire candidate. It totally exclude that specific bean definition from being available to the autowiring infrastructure.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
xml version="1.0" encoding="UTF-8"?>
<beans>
    <context:annotation-config />
      
    <bean id="employee" class="com.howtodoinjava.autowire.constructor.EmployeeBean" autowire="constructor">
        <property name="fullName" value="Lokesh Gupta"/>
    </bean>
    
    <bean id="humanResource" class="com.howtodoinjava.autowire.constructor.DepartmentBean" >
        <property name="name" value="Human Resource" />
    </bean>
     
    
     <bean id="finance"      class="com.howtodoinjava.autowire.constructor.DepartmentBean" autowire-candidate="false">
        <property name="name" value="Finance" />
    </bean>
</beans>
2) Another option is to limit autowire candidates based on pattern-matching against bean names. The top-level element accepts one or more patterns within its ‘default-autowire-candidates‘ attribute. For example, to limit autowire candidate status to any bean whose name ends with ‘Impl’, provide a value of ‘*Impl’. To provide multiple patterns, define them in a comma-separated list.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
xml version="1.0" encoding="UTF-8"?>
<beans default-autowire-candidates="*Impl,*Dao">
    <context:annotation-config />
      
    <bean id="employee" class="com.howtodoinjava.autowire.constructor.EmployeeBean" autowire="constructor">
        <property name="fullName" value="Lokesh Gupta"/>
    </bean>
    
    <bean id="humanResource" class="com.howtodoinjava.autowire.constructor.DepartmentBean" >
        <property name="name" value="Human Resource" />
    </bean>
     
    
     <bean id="finance"      class="com.howtodoinjava.autowire.constructor.DepartmentBean" autowire-candidate="false">
        <property name="name" value="Finance" />
    </bean>
</beans>
Note that an explicit value of ‘true’ or ‘false’ for a bean definition’s ‘autowire-candidate’ attribute always takes precedence, and for such beans, the pattern matching rules will not apply.
That’s all about autowiring feature available in spring framework. If you have any doubt, please drop a comment.
Sourcecode Download
Happy Learning !!