@Autowired is one of the key annotation in annotation based Dependency Injection. Since version 2.5, Spring provides the @Autowired annotation to discover the beans automatically and inject collaborating beans (other associated dependent beans) into our bean.
In this guide we will look into enabling auto-wiring and various ways of autowiring beans using @Autowired annotation in Spring and Spring Boot application.
1. Enable configuration to use @Autowired
By declaring all the beans in Spring Configuration file, Spring container can autowire relationships between collaborating beans. Following are the various configuration styles can be used to use @Autowired in Spring applications and you can use mixed configurations within same application.
1.1. Using Spring XML
<context:annotation-config />
is used in XML config files to enable annotation based dependency Injection.
Sample Configuration file :
<?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: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:annotation-config /> <context:component-scan base-package="com.javabydeveloper.spring.autowire" /> </beans>
1.2. Using Java Configuration
Following is the sample java based configuration to use @Autowired
to inject dependencies with in com.javabydeveloper.spring.autowire
package.
@Configuration @ComponentScan("com.javabydeveloper.spring.autowire") public class ApplConfigForAutowired { }
1.3. @Autowired in Spring Boot
In a Spring Boot application, auto-wiring is enabled by default. Following is sample code. @SpringBootApplication
automatically loads all configuration files and scans the components in the current package and its sub-packages.
@SpringBootApplication public class SpringBootAutowiredDemoApp { public static void main(String[] args) { // code } }
2. Using @Autowired
After enabling annotation based injection, now let’s look into how we can use @Autowired annotation. @Autowired can be used on following injection points.
- Constructors
- Methods
- Fields and
- Parameters
and dependencies can be injected using by type OR by name OR by @Qualifier.
2.1. @Autowired on Constructors
Firstly let’s use @Autowired on constructor. we will see that SampleService
injected by Spring to the constructor of AutowireDITestService
.
package com.javabydeveloper.spring.autowire.service; @Component public class SampleService { public void sample() { System.out.println("Sample Service"); } }
package com.javabydeveloper.spring.autowire; // imports @Component public class AutowireDITestService { // ... private SampleService sampleService; @Autowired public AutowireDITestService(SampleService sampleService) { this.sampleService = sampleService; } public void test() { System.out.println("\n ------ Autowiring Dependency Injection Results ------"); sampleService.sample(); // ... } // ... }
public class ApplicationAutoWiredDemo { public static void main(String[] args) { ApplicationContext ctxt = new AnnotationConfigApplicationContext(AppConfigForAutowired.class); AutowireDITestService adits = ctxt.getBean(AutowireDITestService.class); adits.test(); // ... } }
2.2. @Autowired on Setters and on Methods
Let’s try adding @Autowired on setter method.
In following example, the setter method is called with ExampleService
instance when AutowireDITestService
created.
package com.javabydeveloper.spring.autowire.service; // imports @Component public class ExampleService { public void example() { System.out.println("Example Service"); } }
package com.javabydeveloper.spring.autowire; // imports @Component public class AutowireDITestService { // ... private ExampleService exampleService; // @Autowired on setter @Autowired public void setExampleService(ExampleService exampleService) { this.exampleService = exampleService; } // ... }
We can also apply @Autowired on methods with any number of arguments.
package com.javabydeveloper.spring.autowire; // imports @Component public class AutowireCustomMethodDITestService { private DemoService demoService; private ExampleService exampleService; private SampleService sampleService; @Autowired public void initialize(DemoService demoService, ExampleService exampleService, SampleService sampleService) { this.demoService = demoService; this.exampleService = exampleService; this.sampleService = sampleService; } // ... }
2.3. @Autowired on Properties
We can use @Autowired on properties, so that we can avoid setters and getters for the autowired properties.
package com.javabydeveloper.spring.autowire.service; @Component public class DemoService { public void demo() { System.out.println("Demo Service"); } }
@Component public class AutowireDITestService { // @Autowired on property @Autowired private DemoService demoService; // ... }
2.4. @Autowired on Parameters
Since 5.0, Spring supports @Autowired annotation on individual methods and constructor parameters. But the only part of the core Spring Framework that actively supports autowired parameters is the JUnit Jupiter support in the spring-test
module.
@SpringJUnitConfig(AppConfigForAutowired.class) class AutowireParametersTest { private SampleService sampleService; // @Autowired on constructor parameters AutowireParametersTest(@Autowired SampleService sampleService) { this.sampleService = sampleService; } // @Autowired on method parameters @Test void injectServicesTest(@Autowired DemoService demoService, @Autowired(required = true) ExampleService exampleService) { demoService.demo(); exampleService.example(); sampleService.sample(); } }
3. @Autowired by Type
By default, Spring does auto-wire by type. we have a class type UserDao
and it’s an implementation of IUserDao
interface. Let’s try auto-wire it in service. There should be only one bean configured for implementation class type for IUserDao
interface in the spring bean, Spring automatically inject by it’s type.
public interface IUserDao { public void result(); }
@Component public class UserDao implements IUserDao { @Override public void result() { System.out.println("User Dao Implementation"); } }
@Component public class AutowireByTypeTestService { @Autowired private IUserDao dao; public void printResults() { System.out.println("\n ------ Autowire By Type Results ------"); dao.result(); } }
ApplicationContext ctxt = new AnnotationConfigApplicationContext(AppConfigForAutowired.class); AutowireByTypeTestService abtts = ctxt.getBean(AutowireByTypeTestService.class); abtts.printResults();
------ Autowire By Type Results ------ User Dao Implementation
4. Ambiguity in using @Autowired
By default, Spring does auto-wire by type. If spring found more than one bean of same type in Spring container, it leads to ambiguity issues and framework trows no-unique bean exceptions. To resolve ambiguity conflicts we need to tell Spring which bean need to inject by Using @Autowired by name OR by specifying bean with @Qualifier OR @Primary .
5. @Autowired by name
Let’s say we have IDao
interface CustomerDao
and EmployeeDao
are its implementation classes. Spring will inspect the container and look for a bean with the exact name as the property to autowire it. Let’s see an example.
public interface IDao { public void result(); }
@Component public class CustomerDao implements IDao { @Override public void result() { System.out.println("Customer Dao Implementation"); } }
@Component public class EmployeeDao implements IDao { @Override public void result() { System.out.println("Employee Dao Implementation"); } }
@Component public class AutowireByNameTestService { @Autowired private IDao employeeDao; @Autowired private IDao customerDao; public void printResults() { System.out.println("\n ------ Autowire By Name Results ------"); employeeDao.result(); customerDao.result(); } }
ApplicationContext ctxt = new AnnotationConfigApplicationContext(AppConfigForAutowired.class); AutowireByNameTestService abnts = ctxt.getBean(AutowireByNameTestService.class); abnts.printResults();
------ Autowire By Name Results ------ Employee Dao Implementation Customer Dao Implementation
6. @Autowired by @Qualifier
@Qualifier is used to identify particular bean when you have several implementations of same type. Let’s see an example.
@Component @Qualifier("contact") public class ContactDao implements IDao { @Override public void result() { System.out.println("Contact Dao Implementation"); } }
@Component("address") public class AddressDao implements IDao { @Override public void result() { System.out.println("Address Dao Implementation"); } }
@Component public class AutowireByQualifierTestService { @Autowired @Qualifier("address") private IDao addressDao; @Autowired @Qualifier("contact") private IDao contactDao; public void printResults() { System.out.println("\n ------ Autowire By Qualifier Results ------"); addressDao.result(); contactDao.result(); } }
ApplicationContext ctxt = new AnnotationConfigApplicationContext(AppConfigForAutowired.class); AutowireByQualifierTestService abqts = ctxt.getBean(AutowireByQualifierTestService.class); abqts.printResults();
------ Autowire By Qualifier Results ------ Address Dao Implementation Contact Dao Implementation
7. @Autowired with Optional dependencies
In few cases injecting dependency might be optional, but all the autowired dependencies should be available when a bean is being constructed, otherwise Spring throws exception. There are various ways we can make injecting dependency optional using @Autowired.
7.1. Using @Autowired(required = false)
@Autowired annotation required attribute by default value is true, it means dependency should be available while constructing the bean. We can use @Autowired(required = false) to make injecting dependency is optional by Spring.
@Component public class OptionalDITestService { @Autowired(required = false) private ExerciseService exerciseService; // ... public void doStuff() { System.out.println("\n ------ Autowiring Optional Dependency Injection Results ------"); if(exerciseService != null) exerciseService.exercise(); // ... } }
7.2. Using @Autowired with Java 8 Optional
Alternatively we can use Java 8 Optional instead of required element. Let’s see an example.
@Component public class OptionalDITestService { @Autowired private Optional<ParadigmService> paradigmService; // ... public void doStuff() { // ... if(paradigmService.isPresent()) paradigmService.get().paradigm(); // ... } }
8. Conclusion
In this guide we have seen autowiring beans using @Autowired annotation various ways Spring and Spring Boot applications.
You can get source code from our GitHub repository.
9. References
Other Related Tutorials:
- Spring @Order
- Spring @Lazy
- Spring Boot XML Configuration
- Spring Injecting Collection
- Spring @Primary
- Spring @Import
- Spring Component Scanning
- Spring @ComponentScan Filter Types