Autowiring two beans implementing same interface - how to set default bean to autowire?

前端 未结 5 618
南旧
南旧 2020-11-28 17:50

Background:

I have a Spring 2.5/Java/Tomcat application. There is the following bean, which is used throughout the application in many places

publi         


        
相关标签:
5条回答
  • 2020-11-28 18:06

    I'd suggest marking the Hibernate DAO class with @Primary, i.e. (assuming you used @Repository on HibernateDeviceDao):

    @Primary
    @Repository
    public class HibernateDeviceDao implements DeviceDao
    

    This way it will be selected as the default autowire candididate, with no need to autowire-candidate on the other bean.

    Also, rather than using @Autowired @Qualifier, I find it more elegant to use @Resource for picking specific beans, i.e.

    @Resource(name="jdbcDeviceDao")
    DeviceDao deviceDao;
    
    0 讨论(0)
  • 2020-11-28 18:26

    The reason why @Resource(name = "{your child class name}") works but @Autowired sometimes don't work is because of the difference of their Matching sequence

    Matching sequence of @Autowire
    Type, Qualifier, Name

    Matching sequence of @Resource
    Name, Type, Qualifier

    The more detail explanation can be found here:
    Inject and Resource and Autowired annotations

    In this case, different child class inherited from the parent class or interface confuses @Autowire, because they are from same type; As @Resource use Name as first matching priority , it works.

    0 讨论(0)
  • 2020-11-28 18:28
    The use of @Qualifier will solve the issue.
    Explained as below example : 
    public interface PersonType {} // MasterInterface
    
    @Component(value="1.2") 
    public class Person implements  PersonType { //Bean implementing the interface
    @Qualifier("1.2")
        public void setPerson(PersonType person) {
            this.person = person;
        }
    }
    
    @Component(value="1.5")
    public class NewPerson implements  PersonType { 
    @Qualifier("1.5")
        public void setNewPerson(PersonType newPerson) {
            this.newPerson = newPerson;
        }
    }
    
    Now get the application context object in any component class :
    
    Object obj= BeanFactoryAnnotationUtils.qualifiedBeanOfType((ctx).getAutowireCapableBeanFactory(), PersonType.class, type);//type is the qualifier id
    
    you can the object of class of which qualifier id is passed.
    
    0 讨论(0)
  • 2020-11-28 18:29

    For Spring 2.5, there's no @Primary. The only way is to use @Qualifier.

    0 讨论(0)
  • 2020-11-28 18:30

    What about @Primary?

    Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one 'primary' bean exists among the candidates, it will be the autowired value. This annotation is semantically equivalent to the <bean> element's primary attribute in Spring XML.

    @Primary
    public class HibernateDeviceDao implements DeviceDao
    

    Or if you want your Jdbc version to be used by default:

    <bean id="jdbcDeviceDao" primary="true" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
    

    @Primary is also great for integration testing when you can easily replace production bean with stubbed version by annotating it.

    0 讨论(0)
提交回复
热议问题