4

Similar to this question, but I have this situation. Suppose I have one AccountService interface and two implementations: DefaultAccountServiceImpl and SpecializedAccountServiceImpl, (the classes just like in the previous question). The implementation is in one class, but has different bean implementation for different method. Say:

@RestController
@RequestMapping("/account")
public class AccountManagerRestController {

    @Autowired
    private AccountService service;

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    HttpEntity<?> registerAccount(@RequestBody AccountRegisterRequestBody input) {
        // here the `service` is DefaultAccountServiceImpl
        ...
    }


    @RequestMapping(value = "/register/specialized", method = RequestMethod.POST)
    HttpEntity<?> registerSpecializedAccount(@RequestBody AccountRegisterRequestBody input) {
        // here the `service` is SpecializedAccountServiceImpl
        ...
    }
}
Community
  • 1
  • 1
Morilla Thaisa
  • 121
  • 1
  • 1
  • 10
  • 2
    [This answer](http://stackoverflow.com/questions/11777079/handling-several-implementations-of-one-spring-bean-interface#answer-27339993) demonstrates autowiring two different implementations into one class. Just use the non-specialized implementation in your first method, and the specailized one in your second method. – whistling_marmot Feb 19 '16 at 16:11
  • What is the difference? You just have to create 2 different beans of AccountService and annotate them with `@Qualifier("DefaultAccountServiceImplBeanName")` and `@Qualifier("SpecializedAccountServiceImplBeanName")` respectively. – user2004685 Feb 19 '16 at 16:14
  • So, it CAN'T be assigned to ONE field? – Morilla Thaisa Feb 19 '16 at 16:15
  • @Morilla No you can't! How would Spring know which implementation you are trying to access? – user2004685 Feb 19 '16 at 16:23
  • @user2004685, maybe by annotating the method and pass the qualifier name on it. If such feature exists. – Morilla Thaisa Feb 19 '16 at 16:29
  • @Morilla Unfortunately these is no such feature and you'll have to go through the standard approach. – user2004685 Feb 19 '16 at 16:37

3 Answers3

6

Use @Qualifier("beanName")

@Autowired @Qualifier("service1")
private AccountService service1;

@Autowired @Qualifier("service2")
private AccountService service2;
bilal bilal
  • 124
  • 7
0

I don't really understand the difference. You just have to create two different beans in this case and then annotate them with different @Qualifier.

Still if you do not get it, here is how you can achieve it:

@RestController
@RequestMapping("/account")
public class AccountManagerRestController {

    @Autowired
    @Qualifier("DefaultAccountServiceImpl")
    private AccountService serviceDAS;

    @Autowired
    @Qualifier("SpecializedAccountServiceImpl")
    private AccountService serviceSAS;

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    HttpEntity<?> registerAccount(@RequestBody AccountRegisterRequestBody input) {
        /* Use ServiceDAS Here */
        ...
    }

    @RequestMapping(value = "/register/specialized", method = RequestMethod.POST)
    HttpEntity<?> registerSpecializedAccount(@RequestBody AccountRegisterRequestBody input) {
        /* Use ServiceSAS Here */
        ...
    }
}

Alternatively, you can replace the two annotations with one @Resource annotation like this:

@Resource(name = "DefaultAccountServiceImpl")
private AccountService serviceDAS;

@Resource(name = "SpecializedAccountServiceImpl")
private AccountService serviceSAS;

I prefer this approach as I do not have to use two annotations.

user2004685
  • 9,548
  • 5
  • 37
  • 54
  • So, it CAN'T be assigned to ONE field? What if for several method, not just two, has different implementation? – Morilla Thaisa Feb 19 '16 at 16:30
  • 1
    If you are saying that you have more than 2 implementations for same interface then yes, you'll have to inject `n` number of beans of the same class for each and every implementation. – user2004685 Feb 19 '16 at 16:35
0

For a few implementation, say 1 or two, using the @Qualifier notation is enough, but in the instance that the implementation will grow over time, a more scalable solution will be to utilize the factory pattern.

As such, only the factory class will be responsible for fetching the implementation depending on the implementation argument passed in. Thus, Service 1 implementation could be triggered by passing in "SERVICE1" as a string to the factory class which will return service 1in that manner.

Rbk
  • 72
  • 1
  • 11