如何使用Spring 3.0表达式语言对@Scheduled(fixedDelay)进行参数化?

150

在使用Spring 3.0的定时任务注释功能时,我想将fixedDelay设置为来自我的配置文件的参数,而不是像目前这样将其硬编码到我的任务类中。

@Scheduled(fixedDelay = 5000)
public void readLog() {
        ...
}

不幸的是,使用Spring表达式语言(SpEL)的@Value似乎返回一个字符串对象,而这个字符串对象不能自动装箱为fixedDelay参数所需的长整型值。

5个回答

481

Spring v3.2.2增加了字符串参数以处理这个问题,fixedDelayStringfixedRateStringinitialDelayString现在也可用。

@Scheduled(fixedDelayString = "${my.fixed.delay.prop}")
public void readLog() {
        ...
}

3
@Avi 这个回答是在问题提出三年后才发布的。在问题被提出(和被采纳的答案)时,这个功能并不存在。 - m c
@medveshonok117 收到了。谢谢。 - Avi
8
@medveshonok117 然后呢?现在仍然是最正确的答案。 - eis
在Kotlin中,您需要在字符串中转义$符号: "${my.fixed.delay.prop}" - undefined

52

您可以使用@Scheduled注释,但仅与cron参数一起使用:

@Scheduled(cron = "${yourConfiguration.cronExpression}")

您的5秒间隔可以表示为"*/5 * * * * *"。然而据我所知,您无法提供少于1秒的精度。


12
您展示的cron表达式相当于fixedRate,与fixedDelay不同。 - codebox

26

我猜你不能使用@Scheduled注解。所以,也许对你来说解决方案是使用task-scheduled XML配置。我们来看一下这个例子(从Spring文档复制):

<task:scheduled-tasks scheduler="myScheduler">
    <task:scheduled ref="someObject" method="readLog" 
               fixed-rate="#{YourConfigurationBean.stringValue}"/>
</task:scheduled-tasks>

如果将String转换为Long失败,可以尝试以下方法:

<task:scheduled-tasks scheduler="myScheduler">
    <task:scheduled ref="someObject" method="readLog"
            fixed-rate="#{T(java.lang.Long).valueOf(YourConfigurationBean.stringValue)}"/>
</task:scheduled-tasks>

我没有尝试过这些设置,但希望它能对你有所帮助。


谢谢,XML配置解决了问题。我有点惊讶注释似乎与字符串值紧密相关,无论如何,我会采用老派的方式;-) - ngeek
1
以上配置是否有Java的等效版本? - amique
@Grzegorz Oledzki,在task:scheduled标签下,“someObject”的值将是什么?如果控制器有多个需要固定延迟和初始延迟的方法,那么该如何处理? - Mohit Singh

14
在Spring Boot 2中,我们可以使用Spring表达式语言(SpEL)来设置@Scheduled注解的属性:
@Scheduled(fixedRateString = "${fixed-rate.in.milliseconds}")
public void fixedRate() {
    // do something here
}

@Scheduled(fixedDelayString = "${fixed-delay.in.milliseconds}")
public void fixedDelay() {
    // do something here
}

@Scheduled(cron = "${cron.expression}")
public void cronExpression() {
    // do something here
}

application.properties 文件将如下所示:

fixed-rate.in.milliseconds=5000
fixed-delay.in.milliseconds=4000
cron.expression=0 15 5 * * FRI

就是这样。 这里有一篇详细解释任务调度的文章。


1

我想你可以通过定义一个bean来转换值。我没有尝试过,但是我认为以下类似的方法可能对你有用:

<bean id="FixedDelayLongValue" class="java.lang.Long"
      factory-method="valueOf">
    <constructor-arg value="#{YourConfigurationBean.stringValue}"/>
</bean>

其中:

<bean id="YourConfigurationBean" class="...">
         <property name="stringValue" value="5000"/>
</bean>

谢谢,那听起来是一种方法,但说实话我希望有一个更优雅(“Spring风格”)的解决方案 :-) - ngeek
2
很遗憾,这不会起作用,因为@Scheduled注释属性fixedDelay需要分配一个(长)常量。 - ngeek
啊,没错。那么我猜你不能使用@Scheduled注解来完成它了。 - Grzegorz Oledzki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接