4

I have a servive interface called DataSource and more than 1 implementations like XMLDataSource, DataBaseDataSource etc.

I want to inject(Spring) appropriate implementation to my Struts2 Action based on some user interaction like if User clicks on XML then I need to use XML implementation. Spring has been used for DI framework.

@Autowired
private DataSource dataSource;

Please suggest what is best way to achieve this.

Tapas Jena
  • 1,069
  • 4
  • 14
  • 23
  • Future readers might benefit from my answer here:. https://stackoverflow.com/questions/52338322/spring-di-beans-with-multiple-concretes-picking-one-of-them/52341778#52341778 . It's spring beans xml based but shows how to define multiple concretes and pick one by key-string-name. – granadaCoder Sep 15 '18 at 14:34

4 Answers4

20

If you need to choose the implementation at runtime, based on a user interaction, you have to autowire all the possible implementations of the DataSource interface.

When you autowire a List of the desired interface, Spring will populate the list automatically with an instance of each implementation.

@Autowired
private List<DataSource> dataSources;

It is up to you, then to select the right interface based on the user interaction.

If you need to discriminate based on the bean name, you can also choose to autowire the dictionary of the DataSource object indexed on bean name.

@Autowired
private Map<String, DataSource> dataSourceIndex;

This is available from the 2.5 version of Spring, and you can find here the autowire documentation

Rodney P. Barbati
  • 1,883
  • 24
  • 18
MPavesi
  • 961
  • 6
  • 8
5

When using the @Autowired annotation it's autowiring by type, you should switch to autowiring by name which can be done using the @Qualifier annotation

@Autowired
@Qualifier("yourDataSource")
private DataSource dataSource;
Sergi Almar
  • 8,054
  • 3
  • 32
  • 30
3

Easiest approach would be to inject all the possible implementations and then choose which one to use when the user clicks on the option I think.

DaveH
  • 7,187
  • 5
  • 32
  • 53
0
@Autowired
@Qualifier("legacyDataSource")
private DataSource dataSource;

@Qualifier contains name of bean

or use implementation for inject

@Autowired
    private  XMLDataSource xMLDataSource ;

@Autowired
    private DataBaseDataSource dataBaseDataSource ;
Oleksandr Samsonov
  • 1,067
  • 2
  • 14
  • 29
  • 1
    Would this be better as private DataSource xMLDataSource & private DataSource dataBaseDataSource ? ( Access the services thru the common interface ) – DaveH Sep 26 '13 at 11:39
  • Of course for more flexibility we must use the interface instead of the implementation. In this case only approach is to use @Qualifier annotation. You can use somthing like this `@Autowired Map` or `@Autowired List` for injeting all data sources in spring context. But for some reasons you dont need inject all datasourses (may be only 4 of 10 in your project). – Oleksandr Samsonov Sep 26 '13 at 11:45