Spring Boot异常:BeanCreationException:Injection of autowired dependencies failed;

来源:互联网 发布:微博登陆不了网络异常 编辑:程序博客网 时间:2024/06/05 10:50

问题描述:

在使用spring boot框架实现事务控制demo时,启动项目报错如下:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'queryTypeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.zeber.service.QueryTypeService com.zeber.controller.admin.QueryTypeController.queryTypeService; nested exception is java.lang.IllegalArgumentException: Can not set com.zeber.service.QueryTypeService field com.zeber.controller.admin.QueryTypeController.queryTypeService to com.sun.proxy.$Proxy101at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1202)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)at org.springframework.boot.context.web.SpringBootServletInitializer.run(SpringBootServletInitializer.java:117)at org.springframework.boot.context.web.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:108)at org.springframework.boot.context.web.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:68)at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)

原因:

后来一步步排查发现,只要在实现事务管理的service层类上加入@transactional注解,启动就会报上面的错,不加则没事。网上Google和stack overflow上找了好久,最后尝试把事务注解加在类的接口上,结果就好了。

查看官方案例,Spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional ,在Service中,被 @Transactional 注解的方法,将支持事务;如果注解在类上,则整个类的所有方法都默认支持事务。

关于事务管理器,不管是JPA还是JDBC等都实现自接口 PlatformTransactionManager 如果你添加的是 spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager 实例。如果你添加的是 spring-boot-starter-data-jpa 依赖,框架会默认注入 JpaTransactionManager 实例。正是这些SpringBoot为我们自动做了,所以相对于我们并不透明,我现在依旧不是很明白为什么必须加在接口上,是不是和Spring Boot默认的注解注入有冲突,还是什么原因?

解决方案:

目前可行的是将注解通过接口的方式注入,然后就是在有多个事务管理器时,使用value具体指定使用哪个事务管理器@Transactional(value="txManager1")。

扩展话题

在找这个异常时,看到了这样一封关于Spring Boot接口使用的邮件回复,内容如下图:


在传统观念中,service都需要接口来实现对服务的封装,同时也能降低模块间的耦合。但这封邮件提的思想是没必要使用接口,因为使用接口,Spring AOP还需要为接口类创建代理来处理,主要是Spring不需要接口生成代理,它没接口也可以生成代理,这是我理解的官方开发人员不推荐的原因,当然你使用接口Spring Boot也支持。

2 0