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
相关产品推荐
相关产品推荐

