Categories: Java
Just a trivial note about use of the Spring annotation @Qualifier
. It is most commonly used to inject a specific bean by referencing a (context-wide unique) bean-name. However:
- the annotation can also be used at the bean-definition site, and
- at the injection-site, only
(type, qualifier)
need to be unique
This usage of Qualifier was intended by the library authors, but is not very well documented.
When selecting a bean to inject, Spring needs to be able to select a single candidate from the bean context; it filters by type (ie ignores all beans that don’t match the injected type) and filters by qualifier (ignore all beans that don’t have a matching qualifier). As long as the result is a single bean, that’s fine.
Here’s a trivial spring-integration-test I wrote to demonstrate this:
package net.vonos.example;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
public class CmsDummyIT {
@Configuration
public static class Config {
@Bean
@Qualifier("foo")
public String fooString() {
return "fooval";
}
@Bean
@Qualifier("foo")
public Long fooLong() {
return 3L;
}
@Bean
@Qualifier("bar")
public Long barLong() {
return 4L;
}
}
// ok; there are two objects qualified with "foo" but only one is a Long. Or alternately, two objects
// of type Long, but only one is qualified with "foo"
@Autowired
@Qualifier("foo")
protected Long fooLong;
// ok; there are two objects qualified with "foo" but only one is a String
@Autowired
@Qualifier("foo")
protected String fooString;
// ok; returns both Long beans
@Autowired
protected List<Long> longs;
// here the full bean-name is needed as there are two beans of type Object with qualifier "foo"
@Autowired
@Qualifier("fooLong")
protected Object fooLongAsObj;
@Test
public void contextLoads() {
Assert.assertTrue("Spring context loads", true);
}
}