I am using Spring DI to wire my components and I came across this issue.
I have a BaseService class which has multiple implementations. And the layer above it, has a builder which calls the service to get data to populate POJOs. Service implementation I need to call (ServiceA,ServiceB) changes according to the type of POJO I need to build.
In such case, how can I autowire the service, as it requires late binding the service. How can I tackle this kind of scenario? (Example in Spring DI would really help)
I read similar questions but could not find the answer. And I read that SOA patterns such as Service Host provide different solutions to exact use case.
Please help. Thanks
Injectable constructors are annotated with @Inject and accept zero or more dependencies as arguments. @Inject can apply to at most one constructor per class. @Inject is optional for public, no-argument constructors when no other constructors are present. This enables injectors to invoke default constructors.
The annotation @Inject allows Dagger to call the constructor of the injected class to create an instance of a class, twitterApi . However, there are some cases that we may not call a constructor directly. For example: Interfaces.
Dependency injection (DI) is a technique widely used in programming and well suited to Android development. By following the principles of DI, you lay the groundwork for good app architecture. Implementing dependency injection provides you with the following advantages: Reusability of code.
The goal of the dependency injection technique is to remove this dependency by separating the usage from the creation of the object. This reduces the amount of required boilerplate code and improves flexibility.
How about using a FactoryBean
:
public class BuilderFactory implements FactoryBean<Builder> {
@Autowired
private ApplicationContext appContext;
...
@Override
public Builder getObject() {
Builder builder = new Builder();
switch(something()) {
case "foo":
builder.service = new ServiceA();
break;
case "bar":
builder.service= new ServiceB();
break;
...
default:
//handle cases where it's unclear which type to create
}
return builder;
}
}
where Builder
instances have a public/package-private field BaseService service
that gets called in their getData()
, buildPojos()
and wherever other methods.
(you could also use static factory methods to instantiate Builder
if you want this field to be private)
You can use ServiceLocatorFactoryBean. In your case you would do something like this:
public interface BaseServiceLocator {
BaseService lookup(String qualifier); //use whatever qualifier type makes sense here
}
<bean id="serviceLocatorFactoryBean"
class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface"
value="your.package.BaseServiceLocator" />
</bean>
Then your builder would look something like this:
public class Builder {
@Autowired
private BaseServiceLocator baseServiceLocator;
@Override
public YourReturnType businessMethod() {
SomeData data = getData();
BaseService baseService = baseServiceLocator(data.getType()); //here I am assuming that getType() is a String
//whatever
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With