Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dyamically choose service implementation in Spring

I am using spring 3.2 and would like to dynamically choose a service implementation in my controller depending on a condition. Consider I have an interface and two implementations as follows :

public interface DevService {
   public void add(Device device);
}

public class DevServiceImpl implements DevService {
    public void add(Device device) {
    }
}

public class RemoteDevServiceImpl implements DevService {
    public void add(Device device) {
    }
}

So in my controller, depending on whether the action is to be executed on the local site or remote site, I need to either execute it locally or send a command to the remote site to execute it. Essentially the site on which the user clicks determines which service impl to call. Can anybody suggest a clean way to achieve this ?

like image 602
Prince Avatar asked Aug 06 '13 23:08

Prince


People also ask

What is difference between @autowired and @resource in Spring?

@Resource: annotation based on JSR-250. @Resource is quite similar to @Autowired and @Inject, but the main difference is the execution paths taken to find out the required bean to inject. @Resource will narrow down the search first by name then by type and finally by Qualifiers (ignored if match is found by name).

What is the difference between BeanFactory and ApplicationContext?

BeanFactory will create a bean object when the getBean() method is called thus making it Lazy initialization. ApplicationContext loads all the beans and creates objects at the time of startup only thus making it Eager initialization. BeanFactory interface provides basic features only thus requires less memory.

What is Beanfactorypostsprocessor Spring?

BeanFactoryPostProcessor is an interface and beans that implement it are actually beans that undergo the Spring lifecycle (Example below) but these beans don't take part of the other declared beans' lifecycle.


2 Answers

Assuming you need both implementations in production environment (if not - use Spring profiles to clearly split beans between environments). Simple approach would be:

interface DevService
{
   void add(Device d);
   String getName();
}

@Service("devServiceLocal")
class DevServiceLocalImpl implements DevService
{
   void add(Device d) {...}
   String getName() {return "local";}
}

class Controller
{
   @Autowired
   Collection<DevService> services;

   void doSomethingWithService()
   {
      // TODO: Check type somehow
      String servType = "local";
      for(DevService s: services)
      {
         if(servType.equals(s.getName())
         {
            // Call service methods
            break;
         }
      }
   }
}
like image 93
Sergey Makarov Avatar answered Oct 18 '22 21:10

Sergey Makarov


Your question implies that by "dynamically" you mean that you'd like to be able to select at startup time, but that you don't need to be able to change it midrun. If that's the case, I very strongly recommend using @Profile. My usual practice, using annotation-based configuration, is to have a separate @Configuration class for each profile that defines the profile-specific @Beans that need to be available there. It's even easy to define development-only @Controllers that are completely disabled in production mode. Define a class with String constants for each profile to avoid typos.

like image 40
chrylis -cautiouslyoptimistic- Avatar answered Oct 18 '22 21:10

chrylis -cautiouslyoptimistic-