Hazzo
Hazzo

Reputation: 35

How to dynamically call a method on a qualified service?

I have an interface as following:

public interface Solver {
    void execute(final String definition);
}

I have several solver implementations. For example:

@Qualifier("naive")
@Service
public class NaiveSolver implements Solver {
    @Override
    public void execute(final String definition) {
    }
}

@Qualifier("optimal")
@Service
public class OptimalSolver implements Solver {
    @Override
    public void execute(final String definition) {
    }
}

Now, in my database I have the data for these solvers as following:

type:       textual - examples: simple, naive
definition: textual

When fetching this data, I need to map the type column to the actual service instance, so it can solve the provided definition.

So, my question boils down to this: how can I, given a type string, get the instance of the corresponding Solver service instance of which the qualifier is equal to that type? I believe that @Autowired cannot be used here, as I need to find beans dynamically at runtime.

Upvotes: 0

Views: 546

Answers (3)

Nikolai  Shevchenko
Nikolai Shevchenko

Reputation: 7521

Since Spring 4 you can autowire multiple implemetations into a Map where bean qualifier is a key, and the bean itself is a value

@Autowired
private Map<String, Solver> solvers;

void doStuff() {
    String type = ... // obtain type
    Solver solver = solvers.get(type);
    solver.execute(...)
}

Update

Correct way of naming a bean is not

@Qualifier("naive")
@Service

but

@Service("naive")

@Qualifier is used along with @Autowired to ensure the correct bean is injected

@Autowired
@Qualifier("naive")
private Solver naiveSolver;

Upvotes: 2

Michel Foucault
Michel Foucault

Reputation: 1732

You could merge the following solutions:

Upvotes: 0

Igor Konoplyanko
Igor Konoplyanko

Reputation: 9374

You can create configuration which will just hold mapping to your solvers:

@Autowired
@Qualifier("optimal")
private Solver naiveSolver;

@Bean
public Map<String, Solver> mapSolver() {
   Map<String, Solver> map = new HashMap<>();
   map.put("naive", naiveSolver);
   return map;
}

Or even going further you can follow factory pattern which will provide you different instances of solvers.

Another way you can dynamically get those beans from application context.

Upvotes: 1

Related Questions