Spring Batch @StepScope无法生成CGLIB子类
编辑
我创建了一个复制问题的测试项目。 它可以在https://github.com/tomverelst/test-batch找到。
首先运行maven命令exec:java
来启动HSQL数据库。 然后,您可以运行JUnit测试MigrationJobConfigurationTest
来加载Spring应用程序上下文。
原始问题
启动Spring Batch应用程序时,Spring加载我的作业配置时出现以下exception:
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
注释,应用程序将正确启动,但我需要能够将它们用于我的工作。
Spring配置
// 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" ) . 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 ... }
我还不能给你一个真正的答案,但是 我调试了你提供的示例,这种情况正在发生:
-
@Configuration
定义阅读器看到@StepScope
注释,注释用@Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS)
注释@Scope(value = "step", proxyMode = ScopedProxyMode.TARGET_CLASS)
- 读者的CGLIB子类被创建并注册为
reader
而原始bean被注册为scopedTarget.reader
。 -
StepScope
启动并后处理step
范围的bean。 它检测CGLIB扩展reader
定义并尝试为该=> ERROR创建代理。
冲突中有两种代理机制。 有一些非常奇怪的事情,在我看来,这永远不会奏效。 将尝试搜索Spring JIRA。
UPDATE
找到解决方案 – 您需要为步骤范围禁用自动代理 :
从配置文件中轻松删除
; 您不需要显式添加它,因为在批处理命名空间中定义(如步骤范围的官方文档中所述)