标注@Singleton与@Provides的方法被多次调用问题排查
核心错误点
构造函数判断逻辑完全写反
你Library类构造函数里的if (Objects.nonNull(injector))逻辑搞反了:当前代码是injector已经存在时,反而重新创建新的Injector实例,而原本应该是injector为空时才初始化。而且每次调用initializeLib都会new一个Library对象,不管injector有没有初始化,都会执行构造函数里的log.info("Bean getting created"),这就是日志重复打印的直接原因。缺乏线程安全保障
没有做线程同步处理,多线程场景下可能会多次创建injector,导致更多重复实例。Spring的@Singleton约束未生效
虽然你给getSomeExposedComponent加了@Singleton,但initializeLib每次调用都可能生成新的组件实例(因为injector被重复创建),导致Spring的单例约束失效。
修复后的Library代码
public final class Library { private static volatile Injector injector; // 加volatile保证多线程下的实例可见性 private Library() { // 私有构造,避免外部随意实例化 } public static SomeExposedComponent initializeLib(SomeClass someclass) { if (Objects.isNull(injector)) { // 双重检查锁实现线程安全的单例初始化 synchronized (Library.class) { if (Objects.isNull(injector)) { log.info("Bean getting created"); // 若需要将someclass传入Module,需修改LibraryModule构造接收该参数 injector = createInjector(new LibraryModule(someclass)); } } } return injector.getInstance(SomeExposedComponent.class); } }
额外说明
原代码里的SomeClass someclass参数在构造函数中未被使用,你需要确认是否要将该参数传递给LibraryModule,如果是,要修改LibraryModule的构造方法接收该参数,在创建injector时传入。
修正后,只有第一次调用initializeLib时才会打印日志并创建injector,后续调用直接复用已有的injector获取组件实例,配合Spring的@Singleton,就能保证SomeExposedComponent是单例。
内容的提问来源于stack exchange,提问作者siddhartha kumar verma

