在Jenkins中获取Spring错误“名为”x“的Bean必须为[y]类型,但实际上为[$Proxy]类型

voj3qocg  于 2023-03-17  发布在  Jenkins
关注(0)|答案(3)|浏览(185)

我已经调试了一段时间了,我希望有人能在这里提供一些线索。
我有一个使用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之外很好地运行代码。
有什么主意吗?谢谢。

wz3gfoph

wz3gfoph1#

  • 摘自上述问题注解:*

您是否正在Jenkins上运行Cobertura、Sonar或其他代码检测工具?请注意,mvn site也可能配置为在生成的site中包含Cobertura报告。
Cobertura的问题在于它执行了相当繁重的字节码插装,包括添加一些自定义接口。当Spring启动时,它为bean生成代理。如果bean至少有一个接口,它就使用标准的Java代理。否则,它会尝试创建基于类的代理。
我猜在你的例子中使用了CGLIB类代理,但是在Cobertura检测之后Spring又回到了java代理。这导致了启动错误,因为依赖注入需要类(或CGLIB子类)。
长话短说,强制使用CGLIB类代理,您会很好:

<aop:config proxy-target-class="true"/>
jobtbby3

jobtbby32#

使用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,但是由于它是一个代理,因此会崩溃。
解决方案:对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都需要修复这个问题。

mrphzbgm

mrphzbgm3#

我在JUnit测试中遇到过这个问题。我抱怨一个@Component正在使用Cacheable
请查看此链接:https://github.com/spring-projects/spring-boot/issues/12194#issuecomment-368027766
对我来说,修复方法是将其添加到JUnit中

@SpringBootTest
@EnableCaching(proxyTargetClass = true)

相关问题