Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @Autowire two beans of the same class which are not defined in ApplicationContext

I am working on Spring MVC app and encountered a problem. I am new to Spring, so please forgive me if my working is a bit clumsy. Basically I have a java class ContractList. In my application I need two different objects of this class (both of them must be singleton)

public class MyClass {
    @Autowired
    private ContractList contractList;

    @Autowired
    private ContractList correctContractList;

    .. do something..
}

Note that both of these beans are not defined in ApplicationContext.xml. I am using only annotations. So when I try to access them - contractList and correctContractList end up referring to the same object. Is there a way to somehow differentiate them without defining them explicitly in ApplicationContext.xml ?

like image 770
Russell'sTeapot Avatar asked Mar 20 '13 06:03

Russell'sTeapot


2 Answers

You can give qualifiers to the beans:

@Service("contractList")
public class DefaultContractList implements ContractList { ... }

@Service("correctContractList")
public class CorrectContractList implements ContractList { ... }

And use them like this:

public class MyClass {

    @Autowired
    @Qualifier("contractList")
    private ContractList contractList;

    @Autowired
    @Qualifier("correctContractList")
    private ContractList correctContractList;
}

In xml config still using @Autowired this would be:

<beans>
    <bean id="contractList" class="org.example.DefaultContractList" />
    <bean id="correctContractList" class="org.example.CorrectContractList" />

    <!-- The dependencies are autowired here with the @Qualifier annotation -->
    <bean id="myClass" class="org.example.MyClass" />
</beans>
like image 52
RJo Avatar answered Nov 15 '22 02:11

RJo


In the case that you don't have access to the class annotated with @Autowired there may be another thing you can do. You might be able to take advantage of the @Primary annotation if the stars align in your favor.

Assume you have a library class you can't modify:

class LibraryClass{
   @Autowired
   ServiceInterface dependency; 
}

And another class that you do control:

class MyClass{
   @Autowired
   ServiceInterface dependency; 
}

Setup your config like so, and it should work:

@Bean
@Primary
public ServiceInterface libraryService(){
  return new LibraryService();
}

@Bean
public ServiceInterface myService(){
  return new MyService();
}

And annotate MyClass with Qualifier to tell it to use myService. LibraryClass will use the bean annotated with @Primary and MyClass will use the other with this configuration:

class MyClass{
   @Autowired
   @Qualifier("myService")
   ServiceInterface dependency; 
}

This is a rare use, but I used it in a situation where I had my own class that needed to use a legacy implementation as well as a new implementation.

like image 20
Christopher Schneider Avatar answered Nov 15 '22 02:11

Christopher Schneider