我现在已经调试了一段时间了,我希望有人能在这里说清楚。
我使用JDK 1.6将一个Maven项目添加到Jenkins中。我在这个项目中使用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之外运行我的代码
有什么想法吗?谢谢。
答案 0 :(得分:43)
摘自上述问题评论:
你在Jenkins上运行Cobertura,Sonar或其他代码工具吗?请注意,mvn site
也可能配置为在生成的site
中包含Cobertura报告。
Cobertura的问题在于它执行相当繁重的字节码检测,包括添加一些自定义接口。当Spring启动时,它会为bean生成代理。如果bean至少有一个接口,则它使用标准Java代理。否则它会尝试创建基于类的代理。
我想在你的情况下使用了CGLIB类代理,但在Cobertura工具之后,Spring回归到java代理。这导致启动错误,因为依赖注入期望类(或CGLIB子类)。
长话短说,强迫CGLIB类代理,你会没事的:
<aop:config proxy-target-class="true"/>
答案 1 :(得分:0)
使用AspectJ解决了相同的问题。
有一个豆子
@Configuration public class MyConfig{
@Value("classpath:some.properties")
private Resource theResource;
@Bean
public SomeResource getSomeResource()
{
return SomeResource.getOne(theResource);
}
/******/
@Component
public class SomeResource{
public SomeResource(Resource r) {...}
public static getOne(Resource r} { return new SomeResource(r); }
在启用AOP / AspectJ之前,它可以正常工作。该注入可验证SomeResource Bean来自SomeResource类,但是由于它是Proxy,因此会崩溃。
解决方案:对那个Bean使用GLIBC代理而不是AspectJ代理。
@EnableAspectJAutoProxy(proxyTargetClass=false)
public class SomeResource{...}
毫无意义,但现在得到了更清晰的信息
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils
(file:/path/spring-core/5.2.10.RELEASE/spring-core-5.2.10.RELEASE.jar) to method
java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils
Java意味着无法对此方法进行反思。Spring或Java都需要对此进行修复。