获取 Spring 错误“名为“x”的 Bean;必须是 [y] 类型,但实际上是 [$Proxy] 类型”在詹金斯
我已经调试了一段时间了,我希望有人能在这里阐明一些观点。
我有一个使用 JDK 1.6 添加到 Jenkins 中的 Maven 项目。我在这个项目中使用 AOP 来处理数据库事务。
当我在 Jenkins 中运行构建时,我的测试用例失败,并出现以下异常:-
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'dataHandlerClassificationImpl':
Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'writerDataLocationImpl' must be of type [xxx.script.WriterData],
but was actually of type [$Proxy17]
...
...
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'writerDataLocationImpl' must be of type [xxx.script.WriterData],
but was actually of type [$Proxy17]
...
...
DataHandlerClassificationImpl 类看起来像这样:-
@Service
public class DataHandlerClassificationImpl extends DataHandler {
@Resource(name="writerDataLocationImpl")
private WriterData writerData;
...
}
WriterData 是一个具有多个实现的接口。
我可以从 IDE 中毫无问题地执行代码。为了确定这是 Maven 问题还是 Jenkins 问题,我使用命令行导航到 Jenkins 的项目作业文件夹,并且能够运行 mvn test
而不会出现任何错误。
我知道代理错误与 AOP 有关,并且我只能自动连接到接口而不是具体的类...但这里不是这种情况,因为我能够在 Jenkins 之外正常运行我的代码。
有什么想法吗?谢谢。
I have been debugging this for awhile now, and I'm hoping someone could shed some light here.
I have a Maven project that is added into Jenkins, using JDK 1.6. I'm using AOP in this project to handle the database transaction.
When I run the build in Jenkins, my testcase fails with the following exceptions:-
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'dataHandlerClassificationImpl':
Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'writerDataLocationImpl' must be of type [xxx.script.WriterData],
but was actually of type [$Proxy17]
...
...
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'writerDataLocationImpl' must be of type [xxx.script.WriterData],
but was actually of type [$Proxy17]
...
...
The DataHandlerClassificationImpl
class looks something like this:-
@Service
public class DataHandlerClassificationImpl extends DataHandler {
@Resource(name="writerDataLocationImpl")
private WriterData writerData;
...
}
WriterData
is an interface with multiple implementations.
I am able to execute the code without problem from the IDE. To determine whether it is a Maven problem or Jenkins problem, I navigated to the Jenkins' project job folder using command line and I'm able to run mvn test
without any errors.
I know the proxy error has something to do with AOP, and that I can only autowire to an interface instead of a concrete class... but that's not the case here since I'm able to run my code fine outside Jenkins.
Any ideas? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
摘自上述问题评论:
您是否在 Jenkins 上运行 Cobertura、Sonar 或其他代码检测工具?请注意,
mvn site
也可能配置为在生成的site
中包含 Cobertura 报告。Cobertura 的问题在于它执行相当繁重的字节码检测,包括添加一些自定义接口。当 Spring 启动时,它会生成 bean 代理。如果 bean 至少有一个接口,则它使用标准 Java 代理。否则它会尝试创建基于类的代理。
我猜在你的情况下使用了 CGLIB 类代理,但在 Cobertura 检测 Spring 后又回到了 java 代理。这会导致启动错误,因为依赖注入需要类(或 CGLIB 子类)。
长话短说,强制 CGLIB 类代理就可以了:
Excerpt from question comments above:
Are you running Cobertura, Sonar or other code-instrumenting tool on Jenkins? Note that
mvn site
might also be configured to include Cobertura report in generatedsite
.The problem with Cobertura is that it performs pretty heavy byte-code instrumentation including the addition of some custom interfaces. When Spring starts up it generates proxies for beans. If bean has at least one interface, it uses standard Java proxy. Otherwise it tries to create class-based proxy.
I guess in your case the CGLIB class proxy was used but after Cobertura instrumentation Spring fall back to java proxies. This caused startup error because dependency injection expected class (or CGLIB subclass).
To cut long story short, force CGLIB class proxies and you'll be fine:
我在 JUnit 测试中遇到过这个问题。
我抱怨使用
Cacheable
的@Component
请参阅此链接:https://github.com/spring-projects/spring-boot/issues/12194#issuecomment-368027766
对我来说,修复方法是将其添加到 JUnit 中
I've had this issue in JUnit tests.
I complained about a
@Component
which was usingCacheable
Please see this link: https://github.com/spring-projects/spring-boot/issues/12194#issuecomment-368027766
For me the fix was to add this into the JUnit
使用 AspectJ 遇到同样的问题。
有一个 bean w
在启用 AOP/AspectJ 之前它可以正常工作。注入验证 SomeResource bean 来自类 SomeResource,但由于它是代理,因此会崩溃。
解决方案:对该 Bean 使用 GLIBC 代理而不是 AspectJ 代理。
没有意义,但现在得到了更清晰的消息
,意思是 Java 阻止对此方法的反射。Spring 或 Java 都需要修复这个问题。
Got the same problem using AspectJ.
There was a bean w
This works fine until AOP/AspectJ is enabled. The injection validates that the SomeResource bean is from class SomeResource, but since it is a Proxy it crashes.
SOlution: use GLIBC proxy for that Bean instead of AspectJ proxies.
Makes no sense, but now got a clearer message
Meaning Java prevent reflection on this method.Either Spring or Java needs to fix that.