I was asked (and asked myself) many times, what is the best way to avoid error-prone strings in the Spring Boot @Qualifier
annotation. (And of course other annotations.)
What is better than spreading @Qualifier("variantABC")
or @Qualifier("variantCBA")
all over the code? For example, in Spring Batch, I have qualifiers to distinguish between different jobs and their steps that are used at least three or four times.
Is using interfaces or classes with (just) constant strings really the [only|best|cleanest] solution?
public class Variants{
public final static String VARIANT_ABC = "variantABC";
public final static String VARIANT_CBA = "variantCBA";
}
Or can we do better?
I found out, the best solution for me was to use my own annotations instead of using annotations with strings.
Strings in annotations have the obvious disadvantage, that you can easily make typos at one or the other usage. And it could be hard to find the error.
And it is just not clean to have redundant strings all over the code.
Why you should not use the constant interface pattern you can read here: https://en.wikipedia.org/wiki/Constant_interface
And even using a constant class as in the question is not a solution since it requires one place which knows all possible annotations. That doesn't sound like decoupling and clean code either.
For each @Qualifier("....")
annotation which I use more than once, I create a small annotation on my own:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("variantABC")
public @interface VariantABC {}
This way I have to enter the string VariantABC
only once and cannot mistype it.
I can simply use the annotation instead of the Qualifier
annotation on bean declarations:
@Bean
@VariantABC
Foo getImplementationVariantABC() {...}
or all types of injections:
public MyService(@VariantABC Foo foo) {...}
// or
@Autowired
@VariantABC
Foo foo;
(@Target
, @Inherited
and @Documented
and @Inherited are optional. Read the Javadoc for more information of their purpose.)