Kotlin项目中@EnableScheduling注解通过LocalRunner启动失效问题
问题:LocalRunner启动Spring Boot应用时@Scheduled定时任务不执行
我有一个基于Spring Boot 2.6.4、Java 11创建的Kotlin项目,主类代码如下:
@SpringBootApplication @EnableScheduling open class MailApplication { companion object { @JvmStatic fun main(vararg args: String) { runApplication<EcoMailApplication>(*args) } } }
另外我还有一个用于加载额外配置启动应用的类:
object LocalRunner { @JvmStatic fun main(vararg args: String) { System.setProperty("spring.profiles.active", "stubMode,DEV,LOCAL") System.setProperty("logback.configurationFile", "logger/logback.xml") System.setProperty("logging.config", "classpath:logger/logback.xml") MailApplication.main(*args) } }
当通过MailApplication.main启动应用时,带@Scheduled注解的定时服务可正常运行;但通过LocalRunner.main启动时,所有@Scheduled注解的方法都不执行。请问这是什么原因?如何在本地环境启用定时任务?
补充:项目结构如下:
└── com └── acme ├── LocalRunner.kt ├── MailApplication.kt
原因与解决方案
原因分析
问题核心在于Spring Boot的启动上下文识别逻辑:
- 直接运行
MailApplication.main时,Spring Boot会自动将带有@SpringBootApplication的MailApplication作为主配置类,扫描其所在包的组件,同时@EnableScheduling会被正常加载,启动定时任务调度器。 - 通过
LocalRunner启动时,Spring Boot会将LocalRunner视为启动入口的上下文起点,但LocalRunner本身没有@SpringBootApplication或@EnableScheduling注解,导致定时任务的自动配置未被触发。 - 另外主类中
runApplication<EcoMailApplication>(*args)存在类名错误(应为MailApplication),这也可能干扰上下文初始化逻辑。
解决方案
方式一:在LocalRunner中直接指定主配置类启动
修改LocalRunner代码,直接调用runApplication并指定MailApplication作为主配置类,替代调用MailApplication.main的方式:
object LocalRunner { @JvmStatic fun main(vararg args: String) { System.setProperty("spring.profiles.active", "stubMode,DEV,LOCAL") System.setProperty("logback.configurationFile", "logger/logback.xml") System.setProperty("logging.config", "classpath:logger/logback.xml") // 明确指定主配置类启动 runApplication<MailApplication>(*args) } }
这种方式让Spring Boot直接以MailApplication为核心加载配置,自然会启用@EnableScheduling对应的定时任务功能。
方式二:修正主类中的类名错误
先修复MailApplication中runApplication的参数错误,确保上下文初始化正确:
@SpringBootApplication @EnableScheduling open class MailApplication { companion object { @JvmStatic fun main(vararg args: String) { // 修正为当前类MailApplication runApplication<MailApplication>(*args) } } }
如果坚持通过调用MailApplication.main启动,可将LocalRunner改为带Spring注解的开放类(Kotlin的object无法直接使用Spring注解):
@SpringBootApplication @EnableScheduling open class LocalRunner { companion object { @JvmStatic fun main(vararg args: String) { System.setProperty("spring.profiles.active", "stubMode,DEV,LOCAL") System.setProperty("logback.configurationFile", "logger/logback.xml") System.setProperty("logging.config", "classpath:logger/logback.xml") MailApplication.main(*args) } } }
不过这种方式冗余度较高,更推荐方式一。
内容的提问来源于stack exchange,提问作者Gennadiy
相关产品推荐
相关产品推荐

