Skip to content

与 Host / DI 集成

这一页关注 soulsoft_extensions_scheduler,也就是调度器如何接入应用容器和宿主生命周期。

适用场景

  • Web 应用或后台服务里使用调度器
  • 希望任务类通过 DI 获取日志、仓储、配置等服务
  • 想让调度器随宿主自动启动和停止

核心问题

soulsoft_extensions_schedulersoulsoft_scheduler 的集成包,主要解决三件事:

  1. IScheduler 注册到容器
  2. 把任务调度挂到 Hosted Service 生命周期
  3. 让每次任务执行都创建独立作用域

快速开始

先看这几个入口:addScheduler()scheduleJob<T>()addSchedulerHostedService()

cangjie
import soulsoft_extensions_hosting.*
import soulsoft_extensions_injection.*
import soulsoft_extensions_scheduler.*
import soulsoft_scheduler.abstractions.*

public class CleanupJob <: IJob {
    public func execute(_: IJobContext): Unit {
        println("执行清理任务")
    }
}

main(): Int64 {
    let builder = Host.createBuilder()

    builder.services.addScheduler()
        .scheduleJob<CleanupJob>("0 0 2 * * ?")

    builder.services.addSchedulerHostedService()

    builder.build().run()
    return 0
}

核心概念

addScheduler()

这个扩展方法会注册:

  • IScheduler
  • IJobExecutor
  • SchedulerOptions

并返回 SchedulerServiceBuilder 用于继续配置任务。

addSchedulerHostedService()

这个扩展方法会注册 SchedulerHostedService,让调度器随宿主启动和停止。

任务执行作用域

扩展包 README 明确说明:每次任务触发会创建独立的 IServiceScope

这意味着:

  • 任务类可以安全注入作用域服务
  • 每次执行的依赖对象彼此隔离
  • 比手动共享同一个实例更适合真实应用

常见用法

注册多个任务

cangjie
services.addScheduler()
    .scheduleJob<CleanupJob>(Duration.minute * 30)
    .scheduleJob<ReportJob>("0 0 8 * * ?")
    .scheduleJob<ReportJob> { job =>
        job.withCronTrigger("0 0 18 * * ?")
           .withIdentity("evening-report", "reports")
           .withJobData { d => d.set<String>("reportType", "daily") }
    }

任务类中使用 DI

cangjie
public class ReportJob <: IJob {
    private let _logger: ILogger

    public init(logger: ILogger<ReportJob>) {
        _logger = logger
    }

    public func execute(context: IJobContext): Unit {
        if (let Some(type_) <- context.jobData.get<String>("reportType")) {
            _logger.logInformation("生成报表:${type_}")
        }
    }
}

添加任务监听器

cangjie
public class AuditJobListener <: IJobListener & Object {
    public func onJobExecuteBefore(context: IJobContext): Unit {
        println("任务开始:${context.jobDetail.key}")
    }

    public func onJobExecuteAfter(context: IJobContext, exception: ?Exception): Unit {
        if (let Some(ex) <- exception) {
            println("任务异常:${ex.message}")
        }
    }
}

services.addScheduler()
    .addJobListener<AuditJobListener>()
    .scheduleJob<CleanupJob>("0 */5 * * * ?")

API 速查

SchedulerServiceBuilder

方法作用
scheduleJob<TJob>(cronExpr)注册 Cron 任务
scheduleJob<TJob>(cronExpr, startAt)注册延迟启动的 Cron 任务
scheduleJob<TJob>(interval)注册固定间隔任务
scheduleJob<TJob>(interval, startAt)注册延迟启动的间隔任务
scheduleJob<TJob>(configureJob)完整自定义 JobBuilder
addJobListener<TJobListener>()注册任务监听器

生产建议

  • 在应用里优先使用集成包,而不是在业务代码里手动创建裸 Scheduler
  • 任务类保持短小,把复杂业务放进注入的服务层
  • 监听器适合做审计、日志、失败告警,不适合承载主要业务逻辑