Spring Batch @StepScope无法生成CGLIB子类

时间:2013-10-03 12:39:30

标签: java spring spring-batch spring-aop cglib

修改

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

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

原始问题

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

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代理的来源。

我也尝试过使用@Scope(value = "step", proxyMode = ScopedProxyMode.NO),但是在调用JDK代理时会出现堆栈溢出错误,而JDK代理一直在调用它。

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

春季配置

<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
    ...
}

2 个答案:

答案 0 :(得分:5)

我还没有给你一个实际答案(但是)我已经调试了你提供的例子并且发生了这种情况:

  • @Configuration定义阅读器看到@StepScope注释@Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS)
  • 读者的CGLIB子类已创建并注册为reader,而原始bean已注册为scopedTarget.reader
  • StepScope启动并后处理step范围内的bean。它检测CGLIB扩展reader定义并尝试为该=>创建代理。的错误

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


<强>更新

找到解决方案 - 步骤范围需要disable auto-proxying

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

答案 1 :(得分:1)

从配置文件中轻松删除<bean class="org.springframework.batch.core.scope.StepScope" />;您不需要显式添加它,因为它是在批处理命名空间中定义的(如official documentation of Step scope

中所述