Bean Autowiring

Introduction

Basic feature of spring is dependency injection. DI are done by constructors and setter methods.

So far developers have to explicitly configure beans dependencies in XML configuration. Dependency Injection is also called wiring of beans. When developer explicitly defines dependencies in XML configuration then it is called explicit-wiring or manual wiring.

Developers may avoid manual wiring configuration using bean auto-wiring feature.

Spring provides auto-wiring feature, that enable implicit bean dependency injection. You do not need to define bean injection details explicitly in XML configuration file.

There are two ways to configure bean auto-wiring:

1. XML Configuration

Auto-writing can be enabled in XML configuration by autowire attribute in bean tag. Here we are enabling auto-wiring for User bean by specifying auto-wiring mode to byName.

<bean id="user" class="com.sunilos.spring.bean.User" autowire="byName" />

2. Annotations

Auto writing can be done using annotation @Autowired. Annotation @Autowired can be applied on a property, setter method and constructor. Here Order bean has annotated p and i properties by @Autowired annotation to auto-wire Payment and Inventory beans.

@Component("order")

public class Order {

@Autowired

Payment p = null;

@Autowired

Inventory i = null;

...

}

Modes of Auto wiring

Auto wiring is done as per mode values passed to it. There are multiple modes of auto-wiring:

  1. autowire="no" : auto-writing is disabled. Bean references must be defined in the XML file via the <ref/> element (or "ref" attribute). This value is set by default.

  2. autowire="byName" : auto-wiring is done by property name.

  3. autowire="byType" : auto wiring is done by property data type. f data type of property is matched with a bean then bean is auto wired. Bean is auto wired if there is exactly one bean of the property type in the container. If more than one beans are found in container then a fatal error is raised.

  4. autowire="constructor" : Just like "byType" but applied on constructor arguments. If there is not exactly one bean of the constructor argument type in the bean factory, a fatal error is raised.

Configuration of dependency using <property> and <constructor-arg> tags will override auto-wiring.

By Name auto-wiring

In this mode auto-wiring is done by property name. IOC container searches dependent beans by given property name and injects in required bean.

For example User bean is depend on Role bean. User has setRole(role) to inject the role bean dependency. IOC container looks that property name is "role" in setter method so looks up bean in container by name "role" an inject into setter method.

public class User {

private String firstName = null;

private String lastName = null;

private Role role = null;

public void setRole(Role role) {

this.role = role;

}

...

}

<bean id="roleBean" class="com.sunilos.spring.bean.Role" autowire-candidate="true" />

<bean id="user" class="com.sunilos.spring.bean.User" autowire="byName" />

Bean tag has autowire-candidate="true" attribute. Default value of autowire-candidate is true. If you set it false for a bean then bean will not participate in auto-wiring.

Since default value of autowire-candidate is true so following two statements are same:

<bean id="roleBean" class="com.sunilos.spring.bean.Role" autowire-candidate="true" />

<bean id="roleBean" class="com.sunils.spring.bean.Role" />

Here in example of annotation based by name auto wiring. Inventory bean is searched by name "inventory" and injected to the property "i".

@Component("order")

public class Order {

@Autowired

Payment p = null;

@Autowired

@Qualifier("inventory")

Inventory i = null;

...

}

Auto-wiring By Type

In this mode auto-wiring is done by property datatype. IOC container searches dependent beans by property datatype and injects into required bean. Autowire attribute is set to byType in the XML configuration file. Here is following configuration container searches bean of Role type and inject into User bean.

<bean id="user" class="com.sunilos.spring.bean.User" autowire="byType" />

Annotation @Autowired can be used to inject dependencies by type. @Autowired can be applied on setter, constructor or attribute.

Following example applies @Autowired to attribute p. Container will search payment bean by type and inject into order bean.

@Component("order")

public class Order {

@Autowired

Payment p = null;

...

}

Sometimes multiple beans of same class can be registered in container with different names. This will create confusion for IOC container to select a bean by type for dependency injection. In order to avoid this confusion @Qualifier annotation is used along with @Autowired. @Qualifier accepts bean name to be injected.

Auto-wiring By Constructor

It is similar to byType injection. Dependencies are injected by constructors. Beans are identified by types of constructor arguments and injected.

public class User {

public User(Role role) {

this.role = role;

}

...

}


<bean id="user" class="com.sunilos.spring.bean.User" autowire="constructor" />

Annotation @Autowired can be applied on constructors to inject dependencies.

@Component("order")

public class Order {

Payment p = null;

Inventory i = null;

@Autowired

public Order(Payment p, Inventory i) {

this.p= p;

this.i= i;

}

...

}

@Qualifier annotation can be applied on constructor arguments to identify a bean by name from container.

public class Order {

Payment p = null;

Inventory i = null;

@Autowired

public Order(@Qualifier("payment") Payment p, @Qualifier("inventory") Inventory i) {

this.p= p;

this.i= i;

}

...

}

Excluding a bean from auto-wiring

You can exclude a bean from auto-wiring. It is done by setting value of autowire-candidate attribute of <bean> tag to false.

<bean id="roleBean" class="com.sunilos.spring.bean.Role" autowire-candidate="false" />

Creating a primary bean

When we define two or more beans of the same type, and these beans are get autowired by "byType" in some other bean, then an ambiguity arises. To overcome these ambiguities with autowiring by type, spring offers another option, creation of a primary bean. We can create a primary bean by setting the primary attribute of <bean> tag to true. For example,

<bean id="role" scope="prototype" class="com.sunilos.spring.bean.Role" primary="true" />

By setting the primary attribute of <bean> tag to true, the bean becomes a primary bean and the bean gets autowired with the calling bean. But when we declare more than one bean as primary, then a conflict comes and an exception arises.

3. Annotation @Autowired

1. @Autowired annotation

  • It is used to inject bean dependencies.

  • It can be applied on attribute, setter method and constructor.

  • It identifies and resolves bean dependencies using bean type or bean name. @Qualifier annotation is used along with it to identify a bean by name.

  • By default it identifies bean by type and injects dependencies

  • When applied in constructor then it always resolves dependencies by type

  • @Autowired with (required=false) is used to optionally inject a dependency.

Here is example of Order, Payment and Inventory beans. Inventory bean is injected into Order by name and Payment bean is injected using by type.

@Component("order")

public class Order {

//identifies bean by type

@Autowired

Payment p = null;

//identifies bean by name

@Autowired

@Qualifier("inventory")

Inventory i = null;

//identifies beans by type when applied on constructor

@Autowired

public Order(Payment p,Inventory i){

this.p = p;

this.i = i;

}

...

}

2. @Qualifier annotation

The @Qualifier annotation is used along with @Autowired annotation to inject a dependency by name. There may be situation when you have configured one bean with two different names and you want to identify bean by name at the time of dependency injection. In this situation you will use @Qualifier annotation to identify bean by name and inject.

Here in example we have defined bean Inventory and given its name "inventory" by passing bean name in component tag. When we injecting inventory bean in order bean we have used qualifier annotation. We identified inventory bean by name by passing name "inventory" to qualifier annotation.

@Component("inventory")

public class Inventory {

}

@Component("order")

public class Order {

//Auto-wring by Name

@Autowired

@Qualifier("inventory")

Inventory i = null;

}

FAQ

  1. What is auto-wiring and how you can do it?

  2. How many ways are there to configure auto-wiring?

  3. Which are the different modes of auto-wiring?

  4. What are the differences between byName and byType auto-wiring?

  5. What is constructor auto-wiring?

  6. Which auto wiring mode is used by @Autowired annotation?

  7. Can you apply @Autowired annotation on an attribute?

  8. Can you apply @Autowired annotation on a method?

  9. Can you apply @Autowired annotation on a constructor?

  10. Why do you use @Qualifier annotation along with @Autowired?

    1. It is used for auto-wiring by name.

  11. How you can exclude a bean from auto-wiring?

  12. If we have applied both implicit (@Autowired) and explicit wiring ( <property> and <constructor-arg> ) then which one will be applied?