Spring Batch @StepScope无法生成CGLIB子类 [英] Spring Batch @StepScope cannot generate CGLIB subclass

查看:1781
本文介绍了Spring Batch @StepScope无法生成CGLIB子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑

我创建了一个复制问题的测试项目。它可以在 https://github.com/tomverelst/test-batch 找到。

I created a test project that replicates the issue. It can be found at https://github.com/tomverelst/test-batch.

首先运行maven命令 exec:java 以启动HSQL数据库。然后,您可以运行JUnit测试 MigrationJobConfigurationTest 来加载Spring应用程序上下文。

First run the maven command exec:java to start a HSQL database. Then you can run the JUnit test MigrationJobConfigurationTest to load the Spring application context.

原始问题

启动Spring Batch应用程序时,Spring加载我的作业配置时出现以下异常:

When starting my Spring Batch application, I get the following exception when Spring is loading my job's configuration:

Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy34]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy34

这是由我的作业配置中的 @StepScope 注释引起的。它试图使用已经用JDK代理代理的CGLIB来代理一个类,我不知道这个JDK代理的来源。

This is caused by the @StepScope annotation in my job's configuration. It attempts to proxy a class with CGLIB which is already proxied with a JDK proxy and I don't know where this JDK proxy is coming from.

我也尝试过使用 @Scope(value =step,proxyMode = ScopedProxyMode.NO),但是在调用JDK代理时会出现堆栈溢出错误,该代理不断调用自身。

I have also tried using @Scope(value = "step", proxyMode = ScopedProxyMode.NO), but then I get a stack overflow error when invoking the JDK proxy, which keeps invoking itself.

如果我删除 @StepScope 注释,应用程序会正确启动,但我需要能够将它们用于我的工作。

The application starts correctly if I remove the @StepScope annotations, but I need to be able to use them for my jobs.

春季配置

<context:component-scan base-package="com.jnj.rn2.batch" />

<context:annotation-config />

<aop:aspectj-autoproxy proxy-target-class="true" />

<bean class="org.springframework.batch.core.scope.StepScope" />

// Job repository etc
...

MigrationJobConfiguration

@Configuration
public class MigrationJobConfiguration {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Autowired
    private MigrationService migrationService;

    @Bean
    public Job migrationJob() {
        return jobs.get( "migrationJob" )
            .start( migrateCrfStep() )
            .next( indexRequestsStep() )
            .build();
    }

    @Bean
    public Step migrateCrfStep() {
        return steps.get( "migrateCrfStep" )
            .tasklet( migrateCrfTasklet() )
            .build();
    }

    @Bean
    public Step indexRequestsStep() {
        return steps.get( "indexRequestsStep" )
            .<LegacyRequest,LegacyRequest> chunk( 5 )
            .reader( indexRequestReader() )
            .processor( indexRequestProcessor() )
            .writer( indexRequestWriter() )
            .build();
    }

    @Bean
    @StepScope
    public MigrateCrfTasklet migrateCrfTasklet() {
        return new MigrateCrfTasklet();
    }

    @Bean
    @StepScope
    public IndexRequestItemReader indexRequestReader() {
        return new IndexRequestItemReader();
    }

    @Bean
    @StepScope
    public IndexRequestItemProcessor indexRequestProcessor() {
        return new IndexRequestItemProcessor();
    }

    @Bean
    @StepScope
    public IndexRequestItemWriter indexRequestWriter() {
        return new IndexRequestItemWriter();
    }

    // Setters
    ...
}


推荐答案

我无法给你一个实际答案(但是)我调试了你提供的例子,这种情况正在发生:

I can not provide you an actual answer (yet), but I've debugged the example you have provided and this is happening:


  • @Configuration 定义读者看到 @StepScope 注释用 @Scope注释(value =step,proxyMode = ScopedProxyMode.TARGET_CLASS)

  • 读者的CGLIB子类被创建并注册为 reader ,而原始bean注册为 scopedTarget.reader

  • StepScope 启动和后处理步骤范围内的bean。它检测到CGLIB扩展阅读器定义并尝试为其创建代理=> 错误

  • @Configuration definition reader sees @StepScope annotation which is annotated with @Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS)
  • CGLIB subclass of reader is created and registered as reader while the original bean is registered as scopedTarget.reader.
  • StepScope kicks in and post-processes step scoped beans. It detects the CGLIB extended reader definition and tries to create proxy for that => ERROR.

冲突中有两种代理机制。有一些非常奇怪的事情,在我看来,这永远不会奏效。将尝试搜索Spring JIRA。

There are two proxying mechanisms in conflict. There is something really weird going on and it seems to me that this can never work. Will try to search through Spring JIRA.

更新

找到解决方案 - 您需要禁用自动代理

Found solution - you need to disable auto-proxying for the step scope:

<bean class="org.springframework.batch.core.scope.StepScope">
    <property name="autoProxy" value="false" />
</bean>

这篇关于Spring Batch @StepScope无法生成CGLIB子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆