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

SonarQube报单例类非同步写入字段错误的原因咨询

SonarQube 单例类非同步写字段问题解答

问题根因

  • Spring 框架中,标注了@Component、@Configuration等注解的类默认是单例(Singleton) 实例,整个应用运行周期内只会初始化一次,多线程场景下会被多个线程同时访问。
  • 你的代码中UrlItems被@Component标注为单例类,其中的url、location是普通成员变量,对应的set方法没有任何同步控制机制。多线程同时调用set方法写变量时,会出现可见性、竞态条件等线程安全问题,这就是SonarQube触发严重级别Bug的原因。

修复方案

方案1:修正@ConfigurationProperties的标准用法(最推荐)

@ConfigurationProperties绑定的属性类不需要标注@Component注册为单例Bean,你只需要在项目启动类增加@ConfigurationPropertiesScan注解即可完成属性自动绑定,从根源消除单例并发写的风险。
修改后代码示例:

// 启动类增加配置属性扫描注解
@SpringBootApplication
@ConfigurationPropertiesScan
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

@Configuration
@ConfigurationProperties(prefix = "app")
public class UrlConfigs {
   private List<UrlItems> item;
   // 保留Getter & Setter
}

// 去掉@Component注解,作为普通属性POJO使用
public class UrlItems {
   private String url;
   private String location;
   // 保留Getter & Setter
}

方案2:增加同步控制(适用业务要求UrlItems必须为单例且支持运行时修改的场景)

如果业务确实需要将UrlItems注册为单例Bean且存在运行时修改属性的需求,可以通过两种方式实现同步控制:

  1. 给set方法增加synchronized关键字,保证同一时间只有一个线程可以执行写操作:
public synchronized void setUrl(String url){
  this.url = url;
}

public synchronized void setLocation(String location) {
   this.location = location;
}
  1. 如果只有赋值操作没有复合读写操作,可以将成员变量声明为volatile保证修改的可见性:
private volatile String url;
private volatile String location;

方案3:禁止运行时修改属性

如果业务上配置属性不需要在运行时修改,直接删除UrlItems的set方法,仅保留getter即可,从逻辑上禁止写操作,也可以消除SonarQube告警。

内容的提问来源于stack exchange,提问作者ima.technophyle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:24:10