Guide to Spring Bean @Autowired

Spring autowired feature enables injection of the object dependency implicitly. In this article, we will cover different features and techniques for the bean autowiring provided by Spring Framework.

 

Introduction

Spring Framework (2.5) introduced the @Autowired annotation for Dependency Injection. In this article, we will learn how to enable Spring bean autowiring feature and the different techniques to inject bean dependencies in our code base.

 

1. Enabling @Autowired Annotations

To enable Spring based injection, we need to pass certain information to the underlying Spring IoC container to detect all components. This can be achieved with the help of AnnotationConfigApplicationContext and @ComponentScan annotation. For Java based configuration

@Configuration
@ComponentScan("com.java.web")
public class WebConfig {
// ...
}

The XML configuration equivalent

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="org.example.web"/>
    <!-- ... -->
</beans>

 

2. Using @Autowired Annotations

Spring Framework provided the following type of bean autowiring.

  • Setter-based autowiring.
  • Constructor based bean wiring.
  • Field or property based autowiring.

 

2.1 @Autowired by Setter

Setter method based annotation allow @Autowired annotation on the setter method. Spring IoC container will call the setter method when the give instance created by Spring.

public class CustomerService {
   
 private ModelMapper modelMapper;

 @Autowired
 public void setModelMapper(ModelMapper modelMapper) {
    this.modelMapper = modelMapper;
 }
}

 

2.2 @Autowired by Constructor

public class CustomerService {

  private ModelMapper modelMapper;

  @Autowired
  public CustomerService(ModelMapper modelMapper) {
     this.modelMapper = modelMapper;
  }
}

 

2.3 @Autowired by Properties

The annotation used directly on properties, eliminating the need for getter and setters.

public class CustomerService {
    @Autowired
    private ModelMapper modelMapper;
}

 

3. @Autowired as Optional

The @Autowired dependency is required by default. This means before injecting the dependency, the dependency being injected should be available.

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

Spring throw NoSuchBeanDefinitionException exception if the required dependency is not available with the container. We can change this behavior by passing false for the required flag.

@Autowired(required =false )
private ModelMapper modelMapper;

 

4. The Qualifier Annotation.

By default, the @Autowired resolve dependencies by type. This works fine until we have only one bean with the same type. Spring framework will throw an exception if more than one bean with the same type is available with the container. The @Autowired annotation will not work in this case, @Qualifier annotation is used for these use case. Let’s take this example

@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
    @Override
    public void enableUser() { }
}
@Service("defaultUserService")
public class DefaultUserService implements UserService {

  @Override
  public void enableUser() {}
}
public class OrderFacade {
  
  @Autowired
  private UserService userService;
}

If we run this code, we may see the following exception on application startup

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'orderController': Unsatisfied dependency expressed through field 'orderFacade'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'orderFacade': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type 'com.javadevjournal.rest.service.UserService' available: expected single matching bean but found 2: defaultUserService,userServiceImpl

 

4.1. Autowiring by @Qualifier

The @Qualifier annotation should be used to show Spring about the type of bean injection requested.

public class OrderFacade {

  @Qualifier("userServiceImpl")
  @Autowired
  private UserService userService;
}

The @Qualifier annotation works by matching the name defined with @Service annotation.

 

4.2. Autowired by Name

Spring framework uses bean name as the default qualifier value. Let’s change the code to understand it more clearly.

@Service("userService")
public class UserServiceImpl implements UserService {
    @Override
    public void enableUser() { }
}
@Service("defaultUserService")
public class DefaultUserService implements UserService {

  @Override
  public void enableUser() {}
}
public class OrderFacade {
  
  @Autowired
  private UserService userService;
}

Spring framework will inject bean of type UserServiceImpl as bean name matches with the definition.

 

Summary

In this article, we discussed Spring autowired and bean autowiring. We covered different bean injection techniques using@Autowired annotation. In the last section, we discussed why to use @Qualifier annotation in your application.

Comments are closed.