Note that @Bean#autowire attribute was deprecated in version 5.1, that was because @Bean factory method argument resolution and @Autowired processing supersede name/type-based bean property injection. In Spring 6.x this attribute has been completely removed.
Autowire.NO is the default mode of autowiring. We have to explicitly use @Autowire annotation at injection point. That means Spring doesn't do automatic wiring in this mode. We have to tell Spring that at what points bean wiring should happen by specifying @Autowired annotation at those points.
On finding @Autowired annotation, Spring attempts to match injection point type with the available registered beans type for a successful injection.
Bean ambiguity
There shouldn't be any conflict (ambiguity), which means there should be no more than one bean instance of the same type registered for a given injection point, otherwise we will have NoUniqueBeanDefinitionException .
Example
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class AutowireNoExample {
public static void main (String[] args) {
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(Config.class);
ClientBean bean = context.getBean(ClientBean.class);
bean.doSomething();
}
@Configuration
public static class Config {
@Bean(autowire = Autowire.NO)
public ClientBean clientBean () {
return new ClientBean();
}
@Bean
public ServiceBean serviceBean () {
return new ServiceBean("Service bean 1");
}
}
private static class ClientBean {
@Autowired
private ServiceBean serviceBean;
public void doSomething () {
System.out.println(serviceBean.getMsg());
}
}
private static class ServiceBean {
private String msg;
public ServiceBean (String msg) {
this.msg = msg;
}
public String getMsg () {
return msg;
}
}
}
OutputService bean 1
If there are two beans available of the required type then the match is performed based on the bean's name. If no match is found then NoUniqueBeanDefinitionException is thrown.
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
public class AutowireNoExample2 {
public static void main (String[] args) {
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(Config.class);
ClientBean bean = context.getBean(ClientBean.class);
bean.doSomething();
}
public static class Config {
@Bean(autowire = Autowire.NO)
public ClientBean clientBean () {
return new ClientBean();
}
@Bean
public ServiceBean serviceBean1 () {
return new ServiceBean("Service Bean 1");
}
@Bean
public ServiceBean serviceBean2 () {
return new ServiceBean("Service Bean 2");
}
}
private static class ClientBean {
@Autowired
private ServiceBean serviceBean;
public void doSomething () {
System.out.println(serviceBean.getMsg());
}
}
private static class ServiceBean {
private String msg;
public ServiceBean (String msg) {
this.msg = msg;
}
public String getMsg () {
return msg;
}
}
} Outputorg.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'clientBean': Unsatisfied dependency expressed through field 'serviceBean'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.logicbig.example.AutowireNoExample2$ServiceBean' available: expected single matching bean but found 2: serviceBean1,serviceBean2 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue (AutowiredAnnotationBeanPostProcessor.java:660) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject (AutowiredAnnotationBeanPostProcessor.java:640) at org.springframework.beans.factory.annotation.InjectionMetadata.inject (InjectionMetadata.java:119) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties (AutowiredAnnotationBeanPostProcessor.java:399) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean (AbstractAutowireCapableBeanFactory.java:1413) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean (AbstractAutowireCapableBeanFactory.java:601) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean (AbstractAutowireCapableBeanFactory.java:524) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0 (AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton (DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean (AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean (AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons (DefaultListableBeanFactory.java:944) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization (AbstractApplicationContext.java:918) at org.springframework.context.support.AbstractApplicationContext.refresh (AbstractApplicationContext.java:583) at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init> (AnnotationConfigApplicationContext.java:93) at com.logicbig.example.AutowireNoExample2.main (AutowireNoExample2.java:20) at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Method.java:498) at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:282) at java.lang.Thread.run (Thread.java:748) Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.logicbig.example.AutowireNoExample2$ServiceBean' available: expected single matching bean but found 2: serviceBean1,serviceBean2 at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique (DependencyDescriptor.java:220) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency (DefaultListableBeanFactory.java:1358) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency (DefaultListableBeanFactory.java:1300) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue (AutowiredAnnotationBeanPostProcessor.java:657) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject (AutowiredAnnotationBeanPostProcessor.java:640) at org.springframework.beans.factory.annotation.InjectionMetadata.inject (InjectionMetadata.java:119) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties (AutowiredAnnotationBeanPostProcessor.java:399) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean (AbstractAutowireCapableBeanFactory.java:1413) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean (AbstractAutowireCapableBeanFactory.java:601) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean (AbstractAutowireCapableBeanFactory.java:524) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0 (AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton (DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean (AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean (AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons (DefaultListableBeanFactory.java:944) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization (AbstractApplicationContext.java:918) at org.springframework.context.support.AbstractApplicationContext.refresh (AbstractApplicationContext.java:583) at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init> (AnnotationConfigApplicationContext.java:93) at com.logicbig.example.AutowireNoExample2.main (AutowireNoExample2.java:20) at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Method.java:498) at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:282) at java.lang.Thread.run (Thread.java:748)
To fix above exception either use bean default name or @Qualifier at the injection point.
Using bean default name
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
public class AutowireNoExample3 {
public static void main (String[] args) {
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(Config.class);
ClientBean bean = context.getBean(ClientBean.class);
bean.doSomething();
}
public static class Config {
@Bean(autowire = Autowire.NO)
public ClientBean clientBean () {
return new ClientBean();
}
@Bean
public ServiceBean serviceBean1 () {
return new ServiceBean("Service Bean 1");
}
@Bean
public ServiceBean serviceBean2 () {
return new ServiceBean("Service Bean 2");
}
}
private static class ClientBean {
@Autowired
private ServiceBean serviceBean2;
public void doSomething () {
System.out.println(serviceBean2.getMsg());
}
}
private static class ServiceBean {
private String msg;
public ServiceBean (String msg) {
this.msg = msg;
}
public String getMsg () {
return msg;
}
}
} OutputService Bean 2
Using @Qualifier annotation
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
public class AutowireNoExample4 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(Config.class);
ClientBean bean = context.getBean(ClientBean.class);
bean.doSomething();
}
public static class Config {
@Bean(autowire = Autowire.NO)
public ClientBean clientBean() {
return new ClientBean();
}
@Bean
public ServiceBean serviceBean1() {
return new ServiceBean("Service Bean 1");
}
@Bean
public ServiceBean serviceBean2() {
return new ServiceBean("Service Bean 2");
}
}
private static class ClientBean {
@Autowired
@Qualifier("serviceBean2")
private ServiceBean serviceBean;
public void doSomething() {
System.out.println(serviceBean.getMsg());
}
}
private static class ServiceBean {
private String msg;
public ServiceBean(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
}
} OutputService Bean 2
Example ProjectDependencies and Technologies Used: - spring-context 5.0.20.RELEASE (Spring Context)
Version Compatibility: 3.2.3.RELEASE - 5.3.31
- JDK 8
- Maven 3.8.1
|