[JAVA] [Spring] Autowired multiple beans. (With bonus)

Can be used in such cases

When you want to use multiple (0 ~ n) beans registered in the container by @Autowired.

Premise

Two classes that implement the MyService interface (where doSomething is defined) are defined and registered in the container.


@Component("myServiceImpl1")
public class MyServiceImpl1 implements MyService {

	@Override
	public void doSomething() {
		System.out.println("myServiceImpl1!!")
	}

}

@Component("myServiceImpl2")
public class MyServiceImpl2 implements MyService {

	@Override
	public void doSomething() {
		System.out.println("myServiceImpl2!!")
	}

}

The user wants to use both of them @Autowired. However, if you normally @Autowired, you will get angry with a duplicate bean error, and it is nonsense (depending on your requirements) to add @Qualifier and @Autowired one by one.

Nonsense injection example



@Qualifier("myServiceImpl1")
@Autowired
private MyService service1;

@Qualifier("myServiceImpl2")
@Autowired
private MyService service2;

manner

To @Autowired multiple beans, use the List class on the @ Autowired side.

MyServiceExecuter.java



@Autowired
private List<MyService> services;

public void execServices(){
	services.forEach(s -> s.doSomething());
}

output


myServiceImpl1!!
myServiceImpl2!!

Bonus: Besides List ...

Looking at it in this way, it seems that there are various classes other than List that can be done using Generics.

Map class

If you enter @Autowired in the Map class, you can get a Map with Key as Bean Name and Value as Bean.

@Autowired
private Map<String,MyService> services;

public void printServices(){
	services.get("myServiceImpl1").doSomething();
	services.get("myServiceImpl2").doSomething();
}

output


myServiceImpl1!!
myServiceImpl2!!

Optional class

I don't know if the target bean is registered in the container. If it is registered, I want to use that bean, and if not, I don't have to inject it. In that case

@Autowired(required=false)
private MyService service;

Many of you know that you can avoid the NoSuchBeanDefinitionException by writing required = false. But if you want to write null-safe code, you can use *** Optional. *** ***

@Autowired
private Optional<MyService> service;

If you write this, @Autowired does not need required = false, and above all, it is null safe.

Summary

Spring DI is deep.

I did not find any information about the feeling of a quick search, so I summarized it.

Environment ↓

springBootVersion = '2.0.5.RELEASE'

[Addition] I changed the expression. 2018.09.24

Recommended Posts

[Spring] Autowired multiple beans. (With bonus)
Spring with Kotorin --- 5. Actuator
Spring MyBatis @MapperScan Multiple
Try Dependency Inversion Principle with Multiple Spring Boot Projects
Self-made Validation with Spring
Spring with Kotorin ―― 1. SPRING INITIALIZR
Download with Spring Boot
Generate barcode with Spring Boot
Implement GraphQL with Spring Boot
Get started with Spring boot
Hello World with Spring Boot!
Spring with Kotorin --6 Asynchronous processing
Run LIFF with Spring Boot
SNS login with Spring Boot
File upload with Spring Boot
Spring Boot starting with copy
Spring with Kotorin ―― 7. Service layer
Login function with Spring Security
Use multiple databases with Rails 6.0
Using Mapper with Java (Spring)
Spring Boot starting with Docker
Set cookies with Spring Boot
Use Spring JDBC with Spring Boot
Add module with Spring Boot
Getting Started with Spring Boot
Link API with Spring + Vue.js
Create microservices with Spring Boot
Send email with spring boot