Spring @Qualifier not working when bean is in anot

2019-09-08 07:31发布

问题:

I have a number of Spring beans, some of which are in a shared library jar. I can't seem to get @Qualifier to work.

I have default-autowire set to "byType", this is using Spring 3.1.0.M2 and running as a standalone executable. If I remove "TestTwoBean" from the shared library the project executes as expected.

myproj-shared-lib.jar:

@Service
public class TestOneBean implements ITestBean {
}

@Service
public class TestTwoBean implements ITestBean {
}

myproj.jar:

@Service
public class TestConsumerBean {

    @Autowired @Qualifier("testOneBean")
    private ITestBean bean;

}

I get the "no unique bean with name" exception at runtime:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testConsumerBean' defined in file [-]: Unsatisfied dependency expressed through bean property 'bean': : No unique bean of type [com.myco.ITestBean] is defined: expected single matching bean but found 2: [testOneBean, testTwoBean]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.myco.TestBean] is defined: expected single matching bean but found 2: [testOneBean, testTwoBean] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1167) ...

Does @Qualifier not work in this situation? Is there a known workaround?

回答1:

Are you sure you want to use autowire by type AND annotation injection? Autowire by type means spring will attempt to inject detected setters and constructor parameters using by type lookup even if they aren't annotated for injection.

At the same time you are trying to inject fields by name. Your @Service annotated classes produce beans with names defaulting to the class name, "testOneBean" and "testTwoBean" respectively. @Qualifier uses bean names as correct matches. The recommended way of doing "by name" injection though is by using @Resource(name="testOneBean"). I can only guess spring tries injection by type due to autowire mode set to by type (which I doubt you really need).

I would recommend reverting to default autowire mode and using @Resource for wiring by name.