大家好,我是你们的程序员阿通,我每周都会在这里给大家分享一些干货内容。今天跟大家分享的是Spring依赖注入常见错误案例。
导读Spring的自动注入非常强大,本节主要围绕
Autowired、Qualifier、Value等内置注解,讨论平时开发可能遇到的问题及解决方案。spring自动注入建立在很多隐性的规则之上。只有你把这些规则都烂熟于心了,才能很好地去规避这些问题。案例1:Autowired注入,bean过多,无所适从案例描述:在使用
Autowired时,我们或多或少应该制造或者遭遇过类似的错误:requiredasinglebean,but2werefound
StudentController代码如下:
RestControllerSlf4jValidatedpublicclassStudentController{AutowiredDataServicedataService;RequestMapping(path="students/{id}",method=RequestMethod.DELETE)publicvoiddeleteStudent(PathVariable("id")Range(min=1,max=)intid){dataService.deleteStudent(id);};}DataService代码如下:
publicinterfaceDataService{voiddeleteStudent(intid);}
RepositorySlf4jpublicclassOracleDataServiceimplementsDataService{OverridepublicvoiddeleteStudent(intid){log.info("deletestudentinfomaintainedbyoracle");}}RepositorySlf4jpublicclassMysqlDataServiceimplementsDataService{OverridepublicvoiddeleteStudent(intid){log.info("deletestudentinfomaintainedbymysql");}}问题原因:首先我们先了解下
Autowired发生的核心过程:(1)执行AbstractAutowireCapableBeanFactory#createBean方法:通过构造器反射构造出这个Bean。
(2)执行AbstractAutowireCapableBeanFactory#populateBean方法:填充这个Bean。
在步骤2中,“填充”过程的关键就是执行各种BeanPostProcessor处理器。
深究这个装配过程,又可以细分为两个步骤:
(1)寻找出所有需要依赖注入的字段和方法,参考AutowiredAnnotationBeanPostProcessor#postProcessProperties。
(2)根据依赖信息寻找出依赖并完成注入,以字段注入为例,参考AutowiredFieldElement#inject方法。
问题修正:方法一:显式引用Bean时首字母忽略大小写
Autowired()Qualifier("mysqlDataService")DataServicedataService;案例2:Qualifier指定名称不规范,无所适从案例描述:将案例1的修复改成引入使用
Qualifier首字母大写:Autowired()Qualifier("MysqlDataService")DataServicedataService;启动报错如下:
Exceptionencounteredduringcontextinitialization-cancellingrefreshattempt:org.springframework.beans.factory.UnsatisfiedDependencyException:ErrorcreatingbeanwithnamestudentController:UnsatisfieddependencyexpressedthroughfielddataService;nestedexceptionisorg.springframework.beans.factory.NoSuchBeanDefinitionException:Noqualifyingbeanoftype