If you try to inject something with a qualify where no bean exists for: like
@Inject @Red IApple redApple;
then you will get an: NoSuchBeanDefinitionException
.
This exception occures no matter if you use:
- @Inject
- @Resource
- @Autowire
The reason is simple: Spring DI first search determine all autowire candidates.
- if there is exactly one, the it uses this candidate
- if there is no candidate, it raise a NoSuchBeanDefinitionException
- if there is more then one, it tryes to determine the primery candidate out of the candiates.
@See
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
line 785..809 (3.0.4.RELEASE)
So what you need to do is putting the fall back (Apple) one in the set of candiates, but make sure that it is only used if there is no other candidate. Because there is no way to mark a bean as fall back or less importend, you need to mark the normal bean as more important: @primary
.
So the (proved) solution would be annotating
- the Black and Red Apple with @Black and @Red and with @Primary.
- the default fallback Apple (Apple1) with with @Red and @Black, but without @Primary.
Example:
@Component @Red @Black public class Apple1 implements IApple {} //fall back
@Component @Black @Primary public class Apple2 implements IApple {}
@Component public class AppleEater {
@Inject @Black IApple blackApple; // -> Apple2
@Inject @Red IApple redApple; // -> Apple1
}
Possible improvement: If you don't like to add all annotations (@Black, @Red, @AllOtherStangeColors) to your fall back bean, you could try to implment your your own AutowireCandiateResolver
so that it adds the fall back bean to all candiate lists of the required type (Apple)
@see Reference Documentation: 3.9.4 CustomAutowireConfigurer