是不是很奇怪? 和上面说的不符合啊! 这里 Student 类有 4 个实例, 分别为 student,student02,student03 和 student04.
非但没有在调用时抛出 BeanCreationException 异常, 反而正常运行, 输出 [小红] , 说明注入的是 id 为 student 的 bean.
大胆的猜想: 多个 bean 时, 是根据 Student 的变量名自动匹配 bean id!
即 : 当 @Autowired private Student student; 时
我们的 Student 变量名是 student , 那么在 Spring 为其注入时, 如果有多个 bean 的话就默认去容器中找 bean id 为 student 得那个 bean.
验证一下
把 Student 的变量名改为 student02,@Autowired private Student student02
重启, 并访问 http://localhost:8080/AutowiredTest, 控制台输出:
同样, 改为 student03,student04 控制台相应输出小华, 小玲.
所以我们的大胆猜想是正确的! 这里使用的 Spring 版本为 4.2.0.RELEASE.
本文永久链接: https://www.cnblogs.com/ibigboy/p/11236729.html
大胆的猜想, 和上面说的不一致, 那是不是版本兼容了这个问题?
验证一下
把版本改低一点. 首先, 把 Spring 版本改为 2.5(@Autowired 第一次出现在该版本), 这时候 @ResponseBody @Configuration 以及 @Bean 都不能用了 (更高版本才能用).
这时候启动项目, 不报错, 访问 http://localhost:8080/AutowiredTest, 报错:
控制台错误信息:
严重: Context initialization failed
- org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'autowiredTestController': Autowiring of fields failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.autowiredtest.entity.Student com.autowiredtest.controller.AutowiredTestController.student02; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.autowiredtest.entity.Student] is defined: expected single matching bean but found 2: [student, student02]
- at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:231)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:978)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:485)
- at java.security.AccessController.doPrivileged(Native Method)
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:455)
- at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
- at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:169)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
- at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:170)
- at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:413)
- at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:735)
- at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:369)
- at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:332)
- at org.springframework.Web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:266)
- at org.springframework.Web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:236)
- at org.springframework.Web.servlet.HttpServletBean.init(HttpServletBean.java:126)
- at javax.servlet.GenericServlet.init(GenericServlet.java:158)
- at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1279)
- at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1192)
- at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:864)
- at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:134)
- at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
- at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
- at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
- at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
- at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
- at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
- at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
- at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
- at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
- at org.apache.tomcat.util.NET.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2441)
- at org.apache.tomcat.util.NET.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2430)
- at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
- at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
- at java.lang.Thread.run(Thread.java:745)
- Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.autowiredtest.entity.Student com.autowiredtest.controller.AutowiredTestController.student02; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.autowiredtest.entity.Student] is defined: expected single matching bean but found 2: [student, student02]
- at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredElement.inject(AutowiredAnnotationBeanPostProcessor.java:375)
- at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:61)
- at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:228)
- ... 35 more
- Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.autowiredtest.entity.Student] is defined: expected single matching bean but found 2: [student, student02]
- at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveDependency(AbstractAutowireCapableBeanFactory.java:425)
- at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredElement.inject(AutowiredAnnotationBeanPostProcessor.java:361)
- ... 37 more
- View Code
控制台错误输出图:
关键的异常信息:
这时候报了预期的错了.
我们再增大版本号, 去测试一下到底是哪个版本号开始兼容了这个问题.
这是版本的发布情况, 采用二分法逼近.
先从当前用的版本 4.2.0.RELEASE 换到 3.2.18.RELEASE(Spring 3.x 的最后一个版本) 也是没问题的, 3.0.0.RELEASE 也没问题, 2.5.5 报错, 2.5.6 报错, 2.5.6.SEC03 报错.
因此可以断定, 从 Spring 3.x 开始兼容了这个问题, 更加人性化.
所以上述关于 @Autowired 的使用规则要发生变化了:
容器中有该类型的候选 Bean
容器中可以含有多个该类型的候选 Bean
Spring 3.x 之前 Spring 容器中只能有一个 Bean; 多个 Bean 报异常 BeanCreationException
Spring 3.x 以后, 可以有多个 Bean 使用 @Autowired 时变量名一定要和该类型多个 Bean 的其中一个相同
(即上文中的 @Autowired private Student student;,student 就是多个 Bean 中其中一个 bean 的 id)
若违反第 4 条规则, 会抛出 BeanCreationException 异常
来源: https://www.cnblogs.com/ibigboy/p/11236729.html