Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance (Late Binding) via Dependency Injection in Java

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)

Builder calling Services

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

like image 412
Chinthaka Dharmasiri Avatar asked Jun 01 '14 04:06

Chinthaka Dharmasiri


People also ask

What does @inject do in Java?

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.

What does the @inject annotation do?

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.

What is dependency injection with example?

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.

What problems does dependency injection solve?

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.


2 Answers

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)

like image 71
drew moore Avatar answered Oct 22 '22 15:10

drew moore


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
  }
like image 22
geoand Avatar answered Oct 22 '22 16:10

geoand