Qualifier Question in Spring DI

Typically, a qualified component will be entered into annotated fields with the same qualifier:

@Component class Apple1 implements IApple {} @Component @Black class Apple2 implements IApple {} class User { @Inject IApple apple; // -> Apple1 @Inject @Black IApple blackApple; // -> Apple2 @Inject @Red IApple redApple; // -> Error: not defined } 

What I want, if a component with a specific qualifier is not defined, I would like to specify a default value, so in the above example redApple instance of redApple will be introduced.

Is it possible? Or can I implement a specific qualifier matching strategy for Spring DI?

** EDIT **

I know that a subclass will work, but this is an example to describe the question, so the subclass is not applicable here.

+4
source share
1 answer

If you are trying to enter something with qualifications, where no bean exists for: like @Inject @Red IApple redApple; , then you get: NoSuchBeanDefinitionException .

This exception does not matter if you use:

  • @Inject
  • @Resource
  • @Autowire

The reason is simple: Spring The first DI search identifies all candidates for auto-collection.

  • if there is exactly one, he uses this candidate
  • If there is no candidate, it raises a NoSuchBeanDefinitionException
  • if there is more than one, he tries to identify a candidate for priming from denominations.

@see org.springframework.beans.factory.support.DefaultListableBeanFactory # doResolveDependency

line 785..809 (3.0.4.RELEASE)

So, what you need to do is postpone the drop (Apple) in the candiates set, but make sure that it is used only if there is no other candidate. Since you cannot mark a bean as a fallback or less importend, you need to mark the normal bean as more important: @primary .

So the (proven) solution will annotate

  • Black and red apple with @Black and @Red and with @Primary.
  • The default backup is Apple (Apple1) 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 do not like to add all annotations (@Black, @Red, @AllOtherStangeColors) to your bean return, you can try to implement your own AutowireCandiateResolver so that it adds a bean drop to all denominations of the required type (Apple) @ see Reference documentation: 3.9.4 CustomAutowireConfigurer

+4
source

Source: https://habr.com/ru/post/1343903/


All Articles