1. Overview

In this tutorial, we’ll look at the Spring’s @Autowired annotation in detail.

When we use annotation-based configuration, @Autowired helps us inject a bean into the target bean. Throughout the tutorial, we’ll investigate different usages of the @Autowired annotation.

2. Sample Application

Let’s start with our sample components:

@Component
public class EmployeeService {

    public void work(){
        System.out.println("Working");
    }
}

Here we have the EmployeeService component without any dependencies.

@Component
public class ManagerService {

    public void manage(){
        System.out.println("Managing");
    }
}

Then we have the ManagerService component which also doesn’t have any dependencies.

We’ll also provide other components when needed in the examples.

2. Injection Points

Now, let’s look at how we can use the @Autowired annotation.

2.1. Constructor Injection with @Autowired

Firstly, we can use @Autowired on a constructor of the target bean.

This is the recommended approach. Because when Spring creates a bean in this way, all dependencies of the bean will be injected with the instance creation:

@Component
public class ConstructorInjectedStoreService {

    private final EmployeeService employeeService;
    private final ManagerService managerService;

    @Autowired
    public ConstructorInjectedStoreService(EmployeeService employeeService,
                                           ManagerService managerService) {
        this.employeeService = employeeService;
        this.managerService = managerService;
    }
}

Here, we’re creating the ConstructorInjectedStoreService bean. Also, we’re declaring the EmployeeService and ManagerService instance fields. Since we’re annotating the constructor with @Autowired, Spring will supply those dependencies to the target bean’s constructor.

2.2. Field Injection with @Autowired

Secondly, we can annotate instance fields with @Autowired.

In contrast to the constructor injection, when a bean is created it may not have all its dependencies injected right away. Though, Spring will wire all dependencies to the target bean eventually:

@Component
public class FieldInjectedStoreService {

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private ManagerService managerService;
}

Here, we have the FieldInjectedStoreService bean. We’re annotating its instance fields with the @Autowired annotation. As a result, Spring will inject related beans to these fields.

2.3. Setter Injection with @Autowired

Another approach we can use is the setter injection. In contrast to field injection, we’ll annotate the setter methods with @Autowired:

@Component
public class SetterInjectedStoreService {

    private EmployeeService employeeService;
    private ManagerService managerService;

    @Autowired
    public void setEmployeeService(EmployeeService employeeService) {
        this.employeeService = employeeService;
    }

    @Autowired
    public void setManagerService(ManagerService managerService) {
        this.managerService = managerService;
    }
}

Here, we have the SetterInjectedStoreService bean whose setter methods are annotated with @Autowired. So during the creation of SetterInjectedStoreService bean, Spring will call these setter methods with related bean instances.

2.4. Custom Method Injection with @Autowired

Similar to setter injection, we can annotate custom methods with @Autowired. As a result, Spring calls these methods with related bean instances:

@Component
public class CustomMethodInjectedStoreService {

    private EmployeeService employeeService;
    private ManagerService managerService;

    @Autowired
    public void prepare(EmployeeService employeeService, ManagerService managerService) {
        this.employeeService = employeeService;
        this.managerService = managerService;
    }
}

Here, we’ve annotated the prepare() method with @Autowired.

2.5. Mixed Dependency Injection

Lastly, we can mix different injection methods:

@Component
public class MixedInjectedStoreService {

    private final EmployeeService employeeService;

    @Autowired
    private ManagerService managerService;

    @Autowired
    public MixedInjectedStoreService(EmployeeService employeeService) {
        this.employeeService = employeeService;
    }
}

Here, we’re using both the field injection and constructor injection approaches.

3. Optional Bean Dependencies

Next, we’ll look at optional bean dependencies.

So far, all of our dependencies were required. Hence if Spring fails to find a suitable bean for the dependency, it will fail the application startup.

However, we may have optional beans, for example, the ones which are activated on a specific environment. Fortunately, the @Autowired annotation lets us define whether our bean dependencies are required or optional:

@Component
public class OptionalDependencyStoreService {

    private final EmployeeService employeeService;
    private final ManagerService managerService;

    @Autowired(required = false)
    private OrderService orderService;

    @Autowired
    public OptionalDependencyStoreService(EmployeeService employeeService,
                                          ManagerService managerService) {
        this.employeeService = employeeService;
        this.managerService = managerService;
    }
}

Here, we’ve annotated OrderService field with @Autowired. Note that we’re setting the required attribute to false. Hence, if Spring cannot find a suitable bean for OrderService, it will continue with the application startup.

4. Without @Autowired

When using constructor injection, there is a special case. If the target bean has only one constructor, we don’t need to annotate it with the @Autowired annotation:

@Component
public class WithoutAutowiredStoreService {

    private final EmployeeService employeeService;
    private final ManagerService managerService;

    public WithoutAutowiredStoreService(EmployeeService employeeService,
                                        ManagerService managerService) {
        this.employeeService = employeeService;
        this.managerService = managerService;
    }
}

Here although we’re using constructor injection, we aren’t using @Autowired.

But note that this is only valid if we’re using Spring Framework 4.3 or above.

5. Injection Multiple Beans

Next, let’s look at how we can auto-wire multiple beans into the target bean.

When we have multiple implementations of an interface, we can inject all of them to the target bean. Furthermore, we can store these beans in an array, List, Set or Map instance:

public interface GoodService {

    void buy();
}

Here we have the GoodService interface which has several implementations.

Let’s see the target bean – GoodManager:

@Component
public class GoodManager {

    @Autowired
    private GoodService[] goodServicesArray;

    @Autowired
    private List<GoodService> goodServicesList;

    @Autowired
    private Set<GoodService> goodServicesSet;

    @Autowired
    private Map<String, GoodService> goodServicesMap;
}

Here, the GoodManager class declares its dependencies in the form of an array or a collection. As a result, Spring will inject all GoodService implementing beans to these fields. For Map type, the key is the name of the injected bean.

6. Overview

In this tutorial, we’ve looked at different usages of Spring’s @Autowired annotation.

Check out the source code over on Github.

Leave a Reply

Close Menu