kane
kane

Reputation: 6027

Can I use another Annotation as the value of the Spring @Qualifier?

Weird situation, but I'm doing a migration from dagger/dropwizard framework into Spring. In the old framework, the code used a bunch of custom @interface Annotations to specify which bean goes where.

For example, there may be an annotation like

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ForAdmin {}

And the providers have code like this

@Provides
@ForAdmin
static Foobar provideFoobar() { ... }

And injects like so

public MyObject(@ForAdmin Foobar foobar) { ... }

In the Spring world, I know I can translate the provider to

@Bean("ForAdmin")
public Foobar provideFoobar() { }

And inject like so

public MyObject(@Qualifier("ForAdmin") Foobar foobar) { ... }

I'm wondering if there is a way to provide the existing @ForAdmin annotation itself as the Qualifier.

Something like...

@Bean(ForAdmin.class)
public Foobar provideFoobar() { }

Is this possible? Is there a better way?

The reason I'd like to do this is to preserve the original annotations so the developers who put them there are still familiar with them and can trace the bean and injection through the annotation they already know about using the IDE.

Upvotes: 0

Views: 169

Answers (1)

Nikolai  Shevchenko
Nikolai Shevchenko

Reputation: 7521

You can use exactly same approach as you used before

Assuming an interface with 2 implementations:

interface Foobar {}

class FoobarAll implements Foobar {}

class FoobarAdmin implements Foobar {}

and a configuration that produces @Beans

@Configuration
class FoobarConfig {
    @Bean
    Foobar provideFoobarAll() { return new FoobarAll(); }

    @ForAdmin
    @Bean
    Foobar provideFoobarAdmin() { return new FoobarAdmin(); }
}

and a class Foobar is injected into

@Component
class FoobarConsumer {
    private final Foobar foobar;

    public FoobarConsumer(@ForAdmin Foobar foobar) {
        this.foobar = foobar;
        System.out.println("I am " + this.foobar.getClass().getSimpleName()); 
        // >>> I am FoobarAdmin
    }
}

P.S. To simplify your code you don't even need a @Configuration to produce @Beans, you can simply place either @Component or @Service Spring annotation on your classes. Then Spring will automatically instantiate these beans.

@Component
class FoobarAll implements Foobar {}

@ForAdmin
@Component
class FoobarAdmin implements Foobar {}

Upvotes: 1

Related Questions