Is there a way to avoid magic strings with Spring @Qualifier annotation

Good evening.

Today I had my first Spring course.
My curiosity had me try things that wasn’t covered and I answered the main question I asked myself today. How do we handle multiple implementations of the same interface? This is done with different annotations:

  • @Primary tells which implementation is to be used by default.
  • @Resource belongs to javax.Annotations package but can be understood by Spring. The class to be used can be set through either its name or type attributes. The former takes a string which first character is lowercase. The latter takes a type and it is why I prefer this one.
@Resource(type = PersonV2.class)
    private IPerson person;
  • @Qualifier belongs to org.springframework.beans.factory.annotation package, so it is the “legit” annotation for such purpose. Unfortunately there is no overload allowing to pass a class I’d know of. It takes a string only.

So I had the idea to make it possible to pass the class name. There is an Introspector Type in java.beans package that does just that through its decapitalize() method.

I wrote a method around that:

public static String beanName(Class $class) {
   String simpleName = $class.getSimpleName();
   return Introspector.decapitalize(simpleName);
}

The problem is Qualifier does not only want a string, but also expects it to be a constant.

It tells otherwise :

Attribute value must be constant

@Qualifier(ClassUtils.beanName(PersonV3.class))

The above code is pretty cool IMHO but it won’t work for the reason mentioned above (wants constant).

The code bellow won’t help neither.

public static final String PERSON_CLASS = ClassUtils.beanName(PersonV3.class);
//...
@Qualifier(PERSON_CLASS)

I guess this has to do with compile time constant against runtime constant but I don’t know how to do such a thing.

Any suggestion?

Many thanks.