You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins共享库中不可变Singleton模式实现技术咨询

嘿,想把你的Jenkins共享库单例改成不可变的?这事儿不难,咱们一步步来!

首先得明确不可变单例的核心要求:实例一旦初始化完成,内部状态就不能被任何外部代码修改。你的原实现里Foo是public的,哪怕调用initialize之后,外部还能直接config.Foo = "新值"改掉它,这显然不符合不可变的要求。

具体实现方案

咱们调整一下类的结构,从字段修饰、初始化逻辑、访问方式三个层面来保证不可变性:

public class Configuration {
    // 单例实例,初始为null,只有初始化后才赋值
    private static Configuration INSTANCE
    // 用final修饰,一旦构造完成就无法修改
    private final String foo

    // 私有构造器,禁止外部直接创建实例
    private Configuration(String foo) {
        this.foo = foo
    }

    // 同步的初始化方法,保证线程安全且只能执行一次
    static synchronized void initialize(String foo) {
        if (INSTANCE != null) {
            throw new IllegalStateException("Configuration已经初始化过了,不能重复执行!")
        }
        INSTANCE = new Configuration(foo)
    }

    // 获取单例实例,必须先调用initialize,否则抛出异常
    static Configuration getInstance() {
        if (INSTANCE == null) {
            throw new IllegalStateException("Configuration还没初始化!请先调用initialize方法。")
        }
        return INSTANCE
    }

    // 只提供只读的getter方法,没有任何修改字段的入口
    public String getFoo() {
        return foo
    }
}

调用方式

现在你需要先完成初始化(只能调用一次),再获取实例访问值:

// 第一步:初始化,传入需要的参数(这里用params.FOO举例)
Configuration.initialize(params.FOO)
// 第二步:获取不可变的单例实例
def config = Configuration.getInstance()
// 只能读取值,无法修改
println 'FOO: ' + config.getFoo()

为什么这样做?

  • 不可变性保障:foo字段用final修饰,构造器赋值后就再也无法修改;同时没有公开字段或setter方法,外部完全没有修改状态的途径。
  • 线程安全:initialize方法加了synchronized,避免Jenkins多线程环境下并发初始化导致的问题。
  • 防止重复初始化:初始化前检查INSTANCE是否已存在,重复调用会抛出异常,避免意外覆盖配置。
  • 强制初始化顺序:调用getInstance前必须先初始化,避免拿到未配置的空实例。

如果需要添加更多配置项,比如从env里取的值,只需要在initialize方法里加参数,然后在构造器里赋值给对应的final字段,再添加对应的getter就可以了。

内容的提问来源于stack exchange,提问作者ISZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:36:42