问题
How can i choose dependency without if else condition.
Suppose i have a interface:
public interface A{
String doSomething(String req);
}
there are two service implements A
:
@Component
public class FirstImpl implements A{
@override
String doSomething(String req){
return "something";
}
}
and:
@Component
public class SecondImpl implements A{
@override
String doSomething(String req){
return "something";
}
}
Now i create a AdapterService class:
@Component
public class AdapterService{
@Autowired
private FirstImpl first;
@Autowired
private SecondImpl second;
public getService(String name){
if("name".equals("First")){
return first;
}else if("name".equals("Second")){
return second;
}
}
}
Now call Implementation:
@Service
public class BusinessService{
@Autowired
private AdapterService adapterService;
void doSomething(String name,String req){
return adapterService.getService(name).doSomething();
}
}
Now if i need to create another class which implements A then need to add condition in ServiceAdapter class. Like "Third".equals(name)
return another injected service. For every new service there need to add another if else condition and inject corresponding service. How can i avoid this Adapter class. Spring dynamically choose depenedency from name.
回答1:
If you have access to applicationContext
object, you can call
applicationContext.getBean(name)
and totally avoid the ServiceAdapter class. Only thing is you need to have those beans in the container.
Try with this:
@Component
public class AdapterService{
@Autowired
private ApplicationContext applicationContext;
public A getService(String name){
return applicationContext.getBean(name,A.class);
}
}
回答2:
Here the java SPI, Service Provider Interface, see here, would do just as well, as trying to use the Spring hammer.
For an interface x.y.z.A
there is a discovery mechanism of implementing classes using the java SPI.
You can have several jars.
They have a text file META-INF/services/x.y.z.A
with implementing class(es) on a line not starting with #
.
As you might not want to instantiate a object of the class before it is selected by name you would either use a runtime annotation on the class, or have the SPI on a factory AFactory with minor construction overhead, creating an A.
ServiceLoader<Dictionary> loader = ServiceLoader.load(A.class);
Iterator<A> dictionaries = loader.iterator();
来源:https://stackoverflow.com/questions/51718836/dynamically-choose-dependency-without-if-else