条件注册
自 v6.2.0 起
@ConditionalOnConfig 注解自 UltiTools-API v6.2.0 起可用。
UltiTools 允许你根据 YAML 配置值来条件性地注册组件。这让服主无需修改代码即可启用或禁用功能。
基本用法
在任意组件类(@Service、@CmdExecutor、@EventListener)上添加 @ConditionalOnConfig:
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 配置:
# config/config.yml
enableWarp: true如果 enableWarp 为 false 或缺失,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 起,建议会跟随容器实际持有的状态:已存在且现在禁用会建议重启移除,不存在且现在禁用则无需重启(改看启动日志),不存在且现在启用会建议重启创建,已存在且现在启用同样无需重启。
注解属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
value | String | (必填) | 相对于插件数据目录的配置文件路径 |
path | String | (必填) | 点分隔或斜杠分隔的 YAML 键路径 |
negate | boolean | false | 如果为 true,在配置值为 false 时注册(反转逻辑) |
示例
条件服务
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
}
}条件事件监听器
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!");
}
}嵌套配置键
使用点号或斜杠来访问嵌套键:
# config/config.yml
features:
teleport:
enabled: true
pvp:
enabled: falsepackage 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 时注册组件:
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)
}完整示例
通过配置控制可选功能的插件:
# config/config.yml
features:
home: true
warp: true
economy: false
welcome: truepackage 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() { }
}@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 语句条件性地注册组件。注解方式更简洁,消除了样板代码。