有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在Spring上下文中使用LocalDate并避免CGLib问题

我有一个用Spring Boot Batch 2.2.2编写的小作业。它将日期作为参数,由于有几个组件需要该日期,因此我将其作为Spring上下文中的一个bean:

@Bean
@StepScope
public Date processingDate(){
if(isEmpty(applicationArguments.getSourceArgs())){
  throw new IllegalArgumentException("No parameter received - expecting a date to be passed as a command line parameter.");
}

SimpleDateFormat sdf = new SimpleDateFormat(EXPECTED_DATE_FORMAT);
String expectedDateFromCommandLine=applicationArguments.getSourceArgs()[0];

try {

  return sdf.parse(expectedDateFromCommandLine);

} catch (ParseException e) {
  throw new IllegalArgumentException("Expecting the parameter date to have this format : "+ EXPECTED_DATE_FORMAT,e);
}
}

它运行良好,没有问题

现在我正在进行一些重构,我认为应该使用LocalDate而不是Date,因为现在推荐使用Java8

@Bean
@StepScope
public LocalDate processingDate(){

    if(isEmpty(applicationArguments.getSourceArgs())){
        throw new IllegalArgumentException("No parameter received - expecting a date to be passed as a command line parameter.");
    }

    String expectedDateFromCommandLine=applicationArguments.getSourceArgs()[0];

    return LocalDate.parse(expectedDateFromCommandLine, DateTimeFormatter.ofPattern(EXPECTED_DATE_FORMAT));

}

但是,Spring不喜欢它:

Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class java.time.LocalDate: 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 java.time.LocalDate
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:208)

我明白,在幕后,Spring通过一些代理和其他方式发挥了一些魔力。。但一定有一个简单的方法让这成为可能,对吗


共 (1) 个答案

  1. # 1 楼答案

    StepScope的Javadoc:

    Marking a @Bean as @StepScope is equivalent to marking it as @Scope(value="step", proxyMode=TARGET_CLASS)
    

    现在,代理模式TARGET_CLASS意味着代理将是CGLIB代理(参见ScopedProxyMode#TARGET_CLASS),这意味着将为代理创建bean类型的子类。由于您正在声明类型为LocalDate的步骤范围bean,它是最终的类,因此Spring(Batch)无法创建代理,因此出现错误

    我看不到有步骤范围的LocalDatebean的附加值。步骤范围bean对于来自步骤/作业执行上下文的作业参数或属性的后期绑定非常有用。但是,如果您真的希望bean是步骤范围的,您可以尝试另一种代理模式,如:

    @Scope(value = "step", proxyMode = ScopedProxyMode.DEFAULT)