Difference between @Qualifier and @Resource
@Autowired
can be used alone . If it is used alone , it will be wired by type . So problems arises if more than one bean of the same type are declared in the container as @Autowired
does not know which beans to use to inject. As a result , use @Qualifier
together with @Autowired
to clarify which beans to be actually wired by specifying the bean name (wired by name)
@Resource
is wired by name too . So if @Autowired
is used together with @Qualifier
, it is the same as the @Resource
.
The difference are that @Autowired
and @Qualifier
are the spring annotation while @Resource
is the standard java annotation (from JSR-250) . Besides , @Resource
only supports for fields and setter injection while @Autowired
supports fields , setter ,constructors and multi-argument methods injection.
It is suggested to use @Resource
for fields and setter injection. Stick with @Qualifier
and @Autowired
for constructor or a multi-argument method injection.
See this:
If you intend to express annotation-driven injection by name, do not
primarily use @Autowired - even if is technically capable of referring
to a bean name through @Qualifier values. Instead, prefer the JSR-250
@Resource annotation which is semantically defined to identify a
specific target component by its unique name, with the declared type
being irrelevant for the matching process.
When to use Qualifier and Primary in Spring
@Primary
indicates that a bean should be given preference when multiple candidates
are qualified to autowire a single-valued dependency.
@Qualifier
indicates specific bean should be autowired when there are multiple candidates.
For example, we have two beans both implement the same interface.
public interface BeanInterface {
String getName();
}
public class Bean1 implements BeanInterface {
@Override
public String getName() {
return "bean 1";
}
}
public class Bean2 implements BeanInterface {
@Override
public String getName() {
return "bean2";
}
}
Here is our service.
@Service
public class BeanService {
@Autowired
private BeanInterface bean;
}
And our configuration.
@Configuration
public class Config {
@Bean("bean1")
public BeanInterface bean1() {
return new Bean1();
}
@Bean("bean2")
public BeanInterface bean2() {
return new Bean2();
}
}
When Spring starts, it will find there are two beans("bean1" and "bean2") both can be autowired to BeanService
since they implement the same interface BeanInterface
. It reports an error in my Idea.
Could not autowire. There is more than one bean of 'BeanInterface' type.
Beans: bean1 (Config.java)
bean2 (Config.java)
And without a hint, Spring does not know which one to use.
So in our case, when we add @Primary
to Config.bean1()
.
@Bean("bean1")
@Primary
public BeanInterface bean1() {
return new Bean1();
}
It tells Spring, "when you find more than one beans that both can be autowired, please use the primary one as your first choose." So, Spring will pick bean1
to autowire to BeanService
.
Here is another way to autowire bean1
to BeanService
by using @Qualifier
in BeanService.class
.
@Service
public class BeanService {
@Autowired
@Qualifier("bean1")
private BeanInterface bean;
}
@Qualifier
will tell Spring, "no matter how many beans you've found, just use the one I tell you."
So you can find both @Qualifier
and @Primary
are telling Spring to use the specific bean when multiple candidates are qualified to autowire. But @Qualifier
is more specific and has high priority. So when both @Qualifier
and @Primary
are found, @Primary
will be ignored.
Here is the test.
@Configuration
public class Config {
@Bean("bean1")
@Primary
public BeanInterface bean1() {
return new Bean1();
}
@Bean("bean2")
public BeanInterface bean2() {
return new Bean2();
}
}
@Service
public class BeanService {
@Autowired
@Qualifier("bean2")
private BeanInterface bean;
@PostConstruct
public void test() {
String name = bean.getName();
System.out.println(name);
}
}
The output is "bean2".
Spring @Autowire and @Qualifier annotation strange behaviour
Well you marked your class with @Component
@Component("myPingPongCoach")
public class PingPongCoach implements Coach
Hence during the component scan, spring founds it and initializes it.
You provide a constructor with one parameter to suppress the default constructor, so Spring will pick it.
Difference between @Primary vs @Autowired with @Qualifier annotations
Read @Primary
as the "default".
If a bean has @Autowired
without any @Qualifier
, and multiple beans of the type exist, the candidate bean marked @Primary
will be chosen, i.e. it is the default selection when no other information is available, i.e. when @Qualifier
is missing.
A good use case is that initially you only had one bean of the type, so none of the code used @Qualifier
. When you then add another bean, you then also add @Qualifier
to both the old and the new bean, so any @Autowired
can choose which one it wants. By also adding @Primary
to the old original bean, you don't have to add @Qualifier
to all the existing @Autowired
. They are "grandfathered" in, so to speak.
@Primary
is also good if e.g. 95% of @Autowired
wants a particular bean. That way, only the @Autowired
that wants the other bean(s) need to specify @Qualifier
. That way, you have primary beans that all autowired wants, and @Qualifier
is only used to request an "alternate" bean.
Related Topics
How to Save Preference User Settings in Java
How to Add an Extra Source Directory for Maven to Compile and Include in the Build Jar
Difference Between Getclass().Getclassloader().Getresource() and Getclass.Getresource()
How to Change MySQL Timezone in a Database Connection Using Java
Help with Packages in Java - Import Does Not Work
How to Open a Windows Named Pipe from Java
Sharing Session Data Between Contexts in Tomcat
Java.Util.Zip - Recreating Directory Structure
How to Write a Key Listener to Track All Keystrokes in Java
Set Private Field Value with Reflection
How to Get Just the Parent Directory Name of a Specific File
Loading Raw 64-Byte Long Ecdsa Public Key in Java
How to Set Auto-Scrolling of Jtextarea in Java Gui
How to Solve the 'Classic' Knapsack Algorithm Recursively