0

In Spring 5, I am able to use a properties file to inject values into fields using the Values annotation. I assumed that the same can be done using the Qualifier annotation, but it doesn't work, instead I have to do the following

import java.lang.annotation.Annotation;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class AutowireCandidateResolverConfigurer implements BeanFactoryPostProcessor {
    private static class EnvironmentAwareQualifierAnnotationAutowireCandidateResolver extends QualifierAnnotationAutowireCandidateResolver {

        private static class ResolvedQualifier implements Qualifier {
            private final String value;
            ResolvedQualifier(String value) { this.value = value; }
            @Override
            public String value() { return this.value; }
            @Override
            public Class<? extends Annotation> annotationType() { return Qualifier.class; }
        }

        @Override
        protected boolean checkQualifier(BeanDefinitionHolder bdHolder, Annotation annotation, TypeConverter typeConverter) {
            if (annotation instanceof Qualifier) {
                Qualifier qualifier = (Qualifier) annotation;
                if (qualifier.value().startsWith("${") && qualifier.value().endsWith("}")) {
                    DefaultListableBeanFactory bf = (DefaultListableBeanFactory) this.getBeanFactory();
                    ResolvedQualifier resolvedQualifier = new ResolvedQualifier(bf.resolveEmbeddedValue(qualifier.value()));
                    return super.checkQualifier(bdHolder, resolvedQualifier, typeConverter);
                }
            }
            return super.checkQualifier(bdHolder, annotation, typeConverter);
        }
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        DefaultListableBeanFactory bf = (DefaultListableBeanFactory) beanFactory;
        bf.setAutowireCandidateResolver(new EnvironmentAwareQualifierAnnotationAutowireCandidateResolver());
    }
}

This is something I found here: How to read Qualifier from property file in spring boot?

I am very new to Spring, so I might be missing something, but isn't this an issue?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • try this approach https://stackoverflow.com/a/12715752/9050514 – deadshot Jun 10 '22 at 15:08
  • What is the problem you're trying to solve? Because as I read this, you're trying to abuse `Qualifier` for something it is not intended for. – Mark Rotteveel Jun 10 '22 at 16:36
  • @MarkRotteveel I want to be able to swap beans out using config, like you could do using an XML configuration. I get that `Qualifier` isn't intended for this use, I am asking why doesn't Spring support something like this? It seems like we're losing functionality by moving from XML to annotations. Unless there's some other way Spring has given us to do this. – Nuan Grobbelaar Jun 11 '22 at 08:27
  • If you're using Spring Boot, you can use conditional annotations from package [`org.springframework.boot.autoconfigure.condition`](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/condition/package-summary.html) (e.g. `@ConditionalOnProperty`, `@ConditionalOnBean`, etc.) – Mark Rotteveel Jun 11 '22 at 08:33
  • @MarkRotteveel yeah that will work! Thanks! I'm still kind of confused as to why this behavior was removed (or left out), is it not something that's really used in a production environment? – Nuan Grobbelaar Jun 11 '22 at 08:40

0 Answers0