Java Spring Batch@StepScope无法生成CGLIB子类
编辑 我创建了一个复制该问题的测试项目。可在以下网址找到 首先运行maven命令Java Spring Batch@StepScope无法生成CGLIB子类,java,spring,spring-batch,spring-aop,cglib,Java,Spring,Spring Batch,Spring Aop,Cglib,编辑 我创建了一个复制该问题的测试项目。可在以下网址找到 首先运行maven命令exec:java,以启动HSQL数据库。然后可以运行JUnit测试MigrationJobConfigurationTest,以加载Spring应用程序上下文 原始问题 @Configuration public class MigrationJobConfiguration { @Autowired private JobBuilderFactory jobs; @Autowired
exec:java
,以启动HSQL数据库。然后可以运行JUnit测试MigrationJobConfigurationTest
,以加载Spring应用程序上下文
原始问题
@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
...
}
启动Spring批处理应用程序时,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
注释引起的。它试图用CGLIB代理一个类,而CGLIB已经用JDK代理了,我不知道这个JDK代理来自哪里
我也尝试过使用@Scope(value=“step”,proxyMode=ScopedProxyMode.NO)
,但是在调用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
...
//作业存储库等
...
迁移作业配置
@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
...
}
@配置
公共类迁移作业配置{
@自动连线
私人建筑工地;
@自动连线
私人StepBuilderFactorySteps;
@自动连线
私有迁移服务迁移服务;
@豆子
公共作业迁移作业(){
返回作业。获取(“迁移作业”)
.start(migrateCrfStep())
.next(indexRequestsStep())
.build();
}
@豆子
公共步骤migrateCrfStep(){
返回步骤。获取(“migrateCrfStep”)
.tasklet(migrateCrfTasklet())
.build();
}
@豆子
公共步骤索引请求步骤(){
返回步骤。获取(“indexRequestsStep”)
.chunk(5)
.reader(indexRequestReader())
.processor(indexRequestProcessor())
.writer(indexRequestWriter())
.build();
}
@豆子
@步进镜
公共迁移ECRTasklet迁移ECRTasklet(){
返回新的MigrateCrfTasklet();
}
@豆子
@步进镜
公共IndexRequestItemReader indexRequestReader(){
返回新的IndexRequestItemReader();
}
@豆子
@步进镜
公共IndexRequestItemProcessor indexRequestProcessor(){
返回新的IndexRequestItemProcessor();
}
@豆子
@步进镜
公共IndexRequestItemWriter indexRequestWriter(){
返回新的IndexRequestItemWriter();
}
//二传手
...
}
轻松从配置文件中删除
;您不需要显式添加它,因为它是在批处理命名空间中定义的(如中所述)我还不能为您提供实际的答案,但我已经调试了您提供的示例,现在正在发生这种情况:
定义阅读器可以看到@Configuration
注释,该注释用@StepScope
@Scope(value=“step”,proxyMode=ScopedProxyMode.TARGET_CLASS)进行注释。
- reader的CGLIB子类被创建并注册为
,而原始bean被注册为reader
scopedTarget.reader
启动和后处理StepScope
scoped bean。它检测CGLIB扩展的step
定义,并尝试为该=>错误创建代理读取器
更新 找到解决方案-您需要为步骤范围:
<bean class="org.springframework.batch.core.scope.StepScope">
<property name="autoProxy" value="false" />
</bean>
这将导致相同的异常。这为我解决了该症状。Spring范围规则充其量是间接的,但一旦你掌握了它们,就有意义了。这在我创建的测试项目中是有效的,但由于某些原因,还没有在我的主项目中。我现在用@EnableBatchProcessing
将XML更改为Java配置,它可以工作。@Pavel在使用@StepScope时,如何将autoProxy设置为false?这是在没有XML配置的情况下发生的。@gsndev如果您没有使用XML配置,您将不会遇到我的回答中描述的冲突(这是OP的问题)。如果您在没有XML配置的情况下遇到类似的异常,那么我建议您提出单独的问题。