在 Spring XML 配置檔引入 task 命名空間並啟用註解驅動:
<beans xmlns:task="https://www.springframework.org/schema/task"
xsi:schemaLocation="...
https://www.springframework.org/schema/task/spring-task-4.0.xsd">
<task:annotation-driven />
</beans>
@Component
public class DailyPiracyJob {
private static final Logger log = LoggerFactory.getLogger(DailyPiracyJob.class);
@Autowired
private AppInfoService appInfoService;
@Scheduled(cron = "0 0 23 * * ?") // 每天 23:00 執行
public void scan() {
try {
List<AppInfo> list = appInfoService.selectAllAppInfo();
if (list != null && !list.isEmpty()) {
for (AppInfo app : list) {
appInfoService.insertDailyPiracy(app.getAppMd5());
}
}
} catch (Exception e) {
log.error("Channel Monitoring failed", e);
}
}
}
@Component:納入元件掃描,讓 Spring 管理 Bean 生命週期。@Scheduled(cron="..."):Core 註解,方法必須 void 無參數;Cron 運算式參考 Quartz 格式。default-lazy-init="true" 會導致 @Scheduled 失效若在 <beans default-lazy-init="true"> 下,所有 Bean 延遲初始化,排程註解解析器無法及早掃描到 Bean,導致任務不執行。解決:移除該屬性,或對排程類別單獨設定 lazy-init="false"。
@Scheduled(fixedRate = 5000) // 上次開始後 5 秒再啟動(併發風險)
@Scheduled(fixedDelay = 5000) // 上次結束後 5 秒再啟動(串行安全)
@Scheduled(initialDelay = 1000, fixedRate = 5000) // 首次延遲 1 秒
@Async 將長耗時任務放入執行緒池,避免阻塞排程執行緒。TaskScheduler 自訂執行緒池大小:@Bean public TaskScheduler scheduler() { return new ThreadPoolTaskScheduler(); }