Spring @Autowired Guide

Welcome to Spring @Autowired Guide. You will learn how the @Autowired annotation works with the help of Spring auto-wiring examples.

Spring Autowiring | amitph

Auto-wiring Beans

Consider a class A that references an instance of another class B (has-a relationship) and wants to reuse its functionality is dependent on B. Spring Dependency Injection resolve all such dependencies throughout the application. However, Spring IoC Container needs to know which class field requires the dependency injected.

A class uses @Autowired annotation on fields, constructors, or setters to declare dependencies and expects Spring to resolve them.

The Spring @Autowired always works by type. The type is not only limited to the Java datatype; it also includes interface types. The Spring can auto-wire by type, by name, or by a qualifier. But every time, the type has to match.

For this tutorial, we have a UserDao, which inherits from an abstract Dao. By adding @Component, we made it a Spring Bean. In the following sections, we will try and inject UserDao instance in our service class and see how auto-wiring works in different scenarios.

UserDao

@Component
public class UserDao extends Dao {}Code language: Java (java)

@Autowire by type

By default, Spring does auto-wire by type. We have a class whose type is UserDao, and supertype is Dao. Let’s try and auto-wire it in a service class using the supertype (Program to Interfaces).

NOTE: Throughout this tutorial the examples are based on Field Based Dependency Injections. That doesn’t mean, we recommend it. Field injections are in-line and helps reader to focus on the business.

UserService

@Component
public class UserService {
    @Autowired private Dao dao;
}Code language: Java (java)

Application

@SpringBootApplication
public class Application implements CommandLineRunner {
    @Autowired UserService service;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println(service.getDao() instanceof UserDao);
    }
}Code language: Java (java)
Output ->  true

Spring straight-away auto wired the UserDao by type.
What if someone creates another implementation of Dao? What will happen to the auto-wiring?
(See in the next section).

@Autowire by name

Consider, someone created a LonginDao, which is also a sub-class of Dao.

@Component
public class LoginDao extends Dao {}Code language: Java (java)

When we run the above application, it fails. The application won’t start and will show the below error.

***************************
APPLICATION FAILED TO START
***************************

Description:

Field dao in com...UserService required a single bean, but 2 were found:
	- loginDao: defined in file [/Users/.../LoginDao.class]
	- userDao: defined in file [/Users/.../UserDao.class]


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Code language: plaintext (plaintext)

Because, this time, Spring found two beans matching the required type, hence couldn’t decide which one to inject. If you have such a scenario, you must use auto-wire by name. We need to change the variable name in the service class. The variable name should match the name of the bean written in the camel case.

@Component
public class UserService {
    @Autowired private Dao userDao;  // or change to loginDao to inject LoginDao instance

}Code language: Java (java)

As stated earlier, Spring uses the bean class name as the bean name. However, you can provide a different name like @Component(“userDataAccessObject”). You will need to use the same name in the service as well.

@Component
public class UserService {
    @Autowired private Dao userDataAccessObject;
}Code language: Java (java)

@Autowire by Qualifier

Auto-wiring by a Qualifier is yet another way of specifying the dependency. A bean can specify a qualifier to identify itself uniquely. The service can use the Qualifier to auto-wire the bean.

@Component
@Qualifier("userDataAccessObject")
public class UserDao extends Dao {}Code language: Java (java)
@Component
public class UserService {
    @Autowired
    @Qualifier("userDataAccessObject")
    private Dao dao;
}Code language: Java (java)

Enable Auto wiring

In a Spring Boot application, auto-wiring is available by default. When a Spring Application Context starts, it runs a Component Scan and scans the target packages to find classes, methods, and Spring annotations fields.

In our example, the component scan revealed that the service class needs a type of Dao bean, and hence Spring was able to inject the dependency.

By default, the component scan targets the current package of the Application class and all of its sub-packages. For a spring auto-wiring to work, it must have the required beans on the Component Scan target packages. We can add additional packages to the component scan using the @ComponentScan annotation.

@ComponentScan(basePackages = {"com.amitph.spring.user", "com.amitph.spring.dog"})Code language: Java (java)

Summary

Today, you learned how to use Spring auto-wiring using @Autowired annotation. Spring Dependency Injection is possible by type, name, and by Qualifier. Springs Component Scan finds all the Spring Beans and dependency requirements in the current package and sub-packages.