一次Bean named ‘xxx‘ is expected to be of type ‘xxxx‘ 记录

1、报错,没有实现Bean

Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'forwardCompanyInfoService' is expected to be of type 'com.suyun.vehicle.data.service.impl.ForwardCompanyInfoServiceImpl' but was actually of type 'com.sun.proxy.$Proxy103'
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.checkBeanNotOfRequiredType(DefaultListableBeanFactory.java:1527) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1505) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
	... 33 common frames omitted

背景:当前类需要提供对外的接口(Dubbo),当前服务的调用,两者方法一个需要组装对象信息(Dto),给外部使用,一个可以直接返回Entity

1、对外需要实现接口

@Service(value = "forwardCompanyInfoService")
public class ForwardCompanyInfoServiceImpl implements IForwardCompanyInfoService {
}

直接使用IForwardCompanyInfoService 调用方法,不报错
2、对内部调用,因为不想转换Dto,想要直接返回Entity,又不能直接暴露返回Entity方法,因为对外的API没有Entity对象,所以用了ForwardCompanyInfoServiceImpl 实习类调用,使用注入方法 @Autowired和@Resource都报上面的错

原理:为什么会报上面的错

1、放入Spring容器的对象并不一定是直接通过类.newIInstance()出来的对象,可能是通过代理进行了增强的一个新的类的对象;

2、Spring当没有强制指定使用Cglib代理时,默认是先使用JDK代理,如果JDK代理失败,才继续使用Cglib代理。
JDK代理:可以简单理解为接口代理,对接口类进行增强;
Cglib代理:代理实现类,对类进行增强;

3、上面的代理因为没有强制指定使用Cglib代理,那就是先使用JDK代理,如果JDK代理失败才使用Cglib代理,因为上面存在接口,所以使用的是JDK代理。

4、放入Spring容器的ForwardCompanyInfoServiceImpl 的实现类其实是一个通过JDK增强后的代理类的实现,而JDK代理,放入容器的类型是一个继承了IForwardCompanyInfoService的类的实现,类型也是IForwardCompanyInfoService,bean的名称也是通过IForwardCompanyInfoService生成的。

5、这时候我通过ForwardCompanyInfoServiceImpl 去注入Bean,首先通过ForwardCompanyInfoServiceImpl 的类型去获取Bean,获取不到,之后通过ForwardCompanyInfoServiceImpl 计算bean名称去获取,也获取不到,这样就会报错了,代码不会因为ForwardCompanyInfoServiceImpl 实现了IForwardCompanyInfoService 就取找到具体的实现。

解决办法

1、直接通过new ForwardCompanyInfoServiceImpl ()调用,不做增强处理;
2、注入IForwardCompanyInfoService,调用Dto方法;
3、类可以多实现,再实现一个新的接口,这个接口不对外,只是当前服务调用,注入类型为这个新的类。
4、指定使用Cglib代理;

我这边偷懒直接返回Dto,启动正常
一次Bean named ‘xxx‘ is expected to be of type ‘xxxx‘ 记录_第1张图片

你可能感兴趣的:(所遇问题,java,spring)