SpringTechnology

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

Auto-wiring Beans

Consider a class has (has-a) another class and wants to reuse its functionality. The former is considered to be dependent on the later. Spring Dependency Injection, resolves all such dependencies throughout the application. However, Spring IoC Container needs to know, which field of a class needs the dependency injected.

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

The Spring @Autowired works always by Type. The type is not only limited to the Java datatypes, it also includes interface types. The Spring can auto-wire by type, by name, or by 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 next 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 {}

@Autowire by Type

By default, Spring does auto-wire by type. We have a class whose type is UserDao and super type is Dao. Let’s try and auto-wire it in a service class using the super type (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;
}

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);
    }
}

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 {}

When we run the above application, it fails. The application won’t start and will show 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

Because, this time Spring found two beans matching to the required type, hence couldn’t decide which one to inject. If you have such a scenario, you have to 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 camel case.

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

}

As stated earlier, the bean class name is considered as the bean name. However you can provide a different name like : @Component("userDataAccessObject"). You will need to use same name in the service as well.

@Component
public class UserService {
    @Autowired private Dao userDataAccessObject;
}

@Autowire by Qualifier

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

@Component
@Qualifier("userDataAccessObject")
public class UserDao extends Dao {}
@Component
public class UserService {
    @Autowired
    @Qualifier("userDataAccessObject")
    private Dao dao;
}

Enable Auto wiring

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

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 is required to have the required beans on the Component Scan target packages. We can add additional packages to the component scan by using @ComponentScan annotation.

@ComponentScan(basePackages = {"com.amitph.spring.user", "com.amitph.spring.dog"})

Summary

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

Leave a Reply

Your email address will not be published. Required fields are marked *