package com.ruoyi.task.api; import com.ruoyi.task.config.TaskSwitch; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * 任务模块对外门面(常驻 Bean)。 * *

为什么必须"常驻"

* 本门面永远是 Spring Bean,不随开关状态增删。这样调用方的 * {@code @Autowired TaskFacade} 在任何开关状态下都不会启动失败 * —— 这与满意度模块的 {@code SatisfactionFacade} 是同一条设计约束 * (历史教训:用 {@code @ConditionalOnProperty} 摘 Bean 会让调用方启动即失败, * 且只在启动时求值一次,做不到"改完参数 10 秒生效")。 * *

⚠️ 与满意度门面的一个差别:本类不实现自己的查询方法

* {@code SatisfactionFacade} 同时实现 {@code SatisfactionApi} 并需 * {@code filter(api -> api != this)} 防自引用递归 —— 因为它要转发到模块内实现。 * 本门面只回答"是否启用",不转发任何查询(查询走 4 个 ruoyi-common 契约), * 因此不存在自引用问题,也就不需要 {@code ObjectProvider} 自过滤那一套。 * 将来若给 {@link TaskApi} 增加需要转发的查询方法,必须补上自引用过滤。 * * @see TaskApi */ @Slf4j @Component public class TaskFacade implements TaskApi { private final TaskSwitch taskSwitch; /** * Spring 使用的构造器。 *

* ⚠️ 必须显式标注 {@code @Autowired}:本类有两个公开构造器 * (另一个给测试/非 Spring 环境用),且没有无参构造器。 * 不标注的话,Spring 找不到"唯一的非默认构造器",会退回查找无参构造器, * 启动即报 {@code No default constructor found}。 *

* 这与满意度模块 {@code SatisfactionFacade} / {@code SatisfactionSwitch} 是同一个坑, * 该规则由 {@code sql/_probe/verify_spring_beans.py} 静态把关 * (**本类已登记进该脚本的扫描范围**,见脚本 MODULE 配置)。 */ @Autowired public TaskFacade(TaskSwitch taskSwitch) { this.taskSwitch = taskSwitch; } /** * 供测试/非 Spring 环境直接构造:{@code sysConfigValue} 就是 * {@code sys_config} 里的 {@code task.enabled} 值,{@code null} 表示"参数行不存在"。 */ public TaskFacade(com.ruoyi.task.config.TaskProperties properties, String sysConfigValue) { this(new TaskSwitch(properties, sysConfigValue)); } @Override public boolean isEnabled() { return taskSwitch.isEnabled(); } /** * 取运行时开关(供拦截器复用同一实例、也供测试断言) */ public TaskSwitch getTaskSwitch() { return taskSwitch; } }