Skip to content

条件注册

自 v6.2.0 起

@ConditionalOnConfig 注解自 UltiTools-API v6.2.0 起可用。

UltiTools 允许你根据 YAML 配置值来条件性地注册组件。这让服主无需修改代码即可启用或禁用功能。

基本用法

在任意组件类(@Service@CmdExecutor@EventListener)上添加 @ConditionalOnConfig

java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.abstracts.command.BaseCommandExecutor;
import com.ultikits.ultitools.annotations.ConditionalOnConfig;
import com.ultikits.ultitools.annotations.command.CmdExecutor;
import org.bukkit.command.CommandSender;

@CmdExecutor(alias = {"warp"}, permission = "myplugin.command.warp")
@ConditionalOnConfig(value = "config/config.yml", path = "enableWarp")
public class WarpCommands extends BaseCommandExecutor {
    // Only registered if enableWarp: true in config.yml

    @Override
    protected void handleHelp(CommandSender sender) {
        sender.sendMessage("/warp");
    }
}

对应的 YAML 配置:

yaml
# config/config.yml
enableWarp: true

如果 enableWarpfalse 或缺失,WarpCommands 类将完全不被注册——没有命令注册、没有内存占用、没有副作用。

只有连接器入口点仍然跳过这个条件

标准 @UltiToolsModule 路径把命令类当容器 bean 解析,条件为 false 的类从一开始就不会被构造成 bean,这条路径在 v6.3.0 之前就已经生效。 v6.3.0 起,监听器包扫描路径也会检查这个条件,补上了唯一真实存在的缺口。 只有连接器入口点(PluginManager.register(UltiToolsPlugin))完全不做组件扫描,那里目前还没有任何地方检查这个条件——跟踪于 issue #334

重载漂移报告

@ConditionalOnConfig 只在组件扫描时(插件启动)求值一次。ul reload 会重新读取配置文件,但它本身不会注册或注销任何组件——它只报告发生了什么变化。

v6.3.0 起,漂移消息会说明容器里实际持有什么,而不只是条件现在给出的答案:

[UltiTools-API] @ConditionalOnConfig drift after reload: com.example.MyService (config/config.yml -> myFeature.enabled) now evaluates to disabled, but the component is already registered. @ConditionalOnConfig is evaluated once at component scan; a restart is required to remove the component.

v6.3.0 之前,建议是一句固定文案

消息过去无条件建议"需要重启",哪怕从未构造过任何实例。v6.3.0 起,建议会跟随容器实际持有的状态:已存在且现在禁用会建议重启移除,不存在且现在禁用则无需重启(改看启动日志),不存在且现在启用会建议重启创建,已存在且现在启用同样无需重启。

注解属性

属性类型默认值说明
valueString(必填)相对于插件数据目录的配置文件路径
pathString(必填)点分隔或斜杠分隔的 YAML 键路径
negatebooleanfalse如果为 true,在配置值为 false 时注册(反转逻辑)

示例

条件服务

java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.annotations.ConditionalOnConfig;
import com.ultikits.ultitools.annotations.Scheduled;
import com.ultikits.ultitools.annotations.Service;

@Service
@ConditionalOnConfig(value = "config/config.yml", path = "economy.enabled")
public class EconomyService {

    @Scheduled(period = 36000, async = true)
    public void distributeTax() {
        // Only runs if economy.enabled: true
    }
}

条件事件监听器

java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.annotations.ConditionalOnConfig;
import com.ultikits.ultitools.annotations.EventListener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;

@EventListener
@ConditionalOnConfig(value = "config/config.yml", path = "welcomeMessage.enabled")
public class WelcomeListener implements Listener {

    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        event.getPlayer().sendMessage("Welcome to the server!");
    }
}

嵌套配置键

使用点号或斜杠来访问嵌套键:

yaml
# config/config.yml
features:
  teleport:
    enabled: true
  pvp:
    enabled: false
java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.abstracts.command.BaseCommandExecutor;
import com.ultikits.ultitools.annotations.ConditionalOnConfig;
import com.ultikits.ultitools.annotations.command.CmdExecutor;
import org.bukkit.command.CommandSender;

@CmdExecutor(alias = {"tp"}, permission = "myplugin.teleport")
@ConditionalOnConfig(value = "config/config.yml", path = "features.teleport.enabled")
public class TeleportCommands extends BaseCommandExecutor {

    @Override
    protected void handleHelp(CommandSender sender) {
        sender.sendMessage("/tp");
    }
}

反转逻辑(negate)

使用 negate = true 在配置值为 false 时注册组件:

java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.annotations.ConditionalOnConfig;
import com.ultikits.ultitools.annotations.Service;

@Service
@ConditionalOnConfig(value = "config/config.yml", path = "maintenance", negate = true)
public class NormalModeService {
    // Only active when maintenance: false (or missing)
}

完整示例

通过配置控制可选功能的插件:

yaml
# config/config.yml
features:
  home: true
  warp: true
  economy: false
  welcome: true
java
package com.ultikits.docs.conditional;

import com.ultikits.ultitools.abstracts.UltiToolsPlugin;
import com.ultikits.ultitools.annotations.UltiToolsModule;

@UltiToolsModule(scanBasePackages = {"com.ultikits.docs.conditional"})
public class MyPlugin extends UltiToolsPlugin {
    @Override
    public boolean registerSelf() { return true; }

    @Override
    public void unregisterSelf() { }
}
java
@CmdExecutor(alias = {"home"}, permission = "myplugin.home")
@ConditionalOnConfig(value = "config/config.yml", path = "features.home")
public class HomeCommands extends BaseCommandExecutor {
    // 已注册(features.home = true)

    @Override
    protected void handleHelp(CommandSender sender) { }
}

@CmdExecutor(alias = {"warp"}, permission = "myplugin.warp")
@ConditionalOnConfig(value = "config/config.yml", path = "features.warp")
public class WarpCommands extends BaseCommandExecutor {
    // 已注册(features.warp = true)

    @Override
    protected void handleHelp(CommandSender sender) { }
}

@Service
@ConditionalOnConfig(value = "config/config.yml", path = "features.economy")
public class EconomyService {
    // 未注册(features.economy = false)
}

@EventListener
@ConditionalOnConfig(value = "config/config.yml", path = "features.welcome")
public class WelcomeListener implements Listener {
    // 已注册(features.welcome = true)
}

v6.2.0 之前

没有 @ConditionalOnConfig 时,开发者需要在 registerSelf() 中手动检查配置值,并使用 if 语句条件性地注册组件。注解方式更简洁,消除了样板代码。

贡献者

The avatar of contributor named as Ling Bao Ling Bao
The avatar of contributor named as Claude Fable 5.1 Claude Fable 5.1

基于 MIT 许可发布