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

Spring @Value注入的MongoURI调用方法时为null异常排查

问题描述
  • 服务启动阶段,@Value从配置文件读取的mongoURI值正常,@PostConstruct标注的初始化方法可以成功打印URI、建立MongoDB连接
  • 调用getUserByAuth0ID方法时抛出java.net.UnknownHostException: null: Name or service not known异常,调试发现该方法执行时成员变量mongoURI值为null
  • 代码中未手动修改mongoURI赋值,此前将mongoURI硬编码为变量时功能运行正常

相关代码

DBConnectService.java:

@Service
public class DBConnectService {
    private static MongoCollection<User> users;
    private static Logger logger = LogManager.getLogger(DBConnectService.class);

    @Value("${package.mongoURI}")
    private String mongoURI;
    
    /** 程序启动时初始化MongoDB连接 */
    @PostConstruct
    public void init() {
        logger.info("Connecting to MongoDB");
        try {
            System.out.println (mongoURI);  // 此处URI可正常打印
            CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());
            CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry);
            MongoClientSettings clientSettings = MongoClientSettings.builder()
                    .applyConnectionString(new ConnectionString(mongoURI))
                    .codecRegistry(codecRegistry)
                    .build();
            
            MongoClient mongoClient = MongoClients.create(clientSettings);
            MongoDatabase database = mongoClient.getDatabase("db");
            users = database.getCollection("users", User.class);
        } catch(Exception e) {
            logger.error("MongoDB connection failure:\n" + e);
        }
    }

    public User getUserByAuth0ID (String authID) {
        System.out.println (mongoURI);  // 此处URI打印值为null
        User user = getUser(authID, "auth0ID");
        if (user == null) {
            user = createUserAccount(authID);
        }
        return user;
    }

    public static User getUser (String info, String field) {
        User user = users.find(eq(field, info)).first();
        return user; 
    }

    public static User createUserAccount (String authID) {
        JsonObject newUserInfo = Auth0Service.getUserInfo(authID);
        
        if (newUserInfo.get("email_verified").getAsBoolean()) {
            
            User newUser = new User()
                    .setEmail(newUserInfo.get("email").getAsString())
                    .setName(newUserInfo.get("name").getAsString())
                    .setAuth0ID(authID);
            
            users.insertOne(newUser);
            
            return newUser;
        } else {
            logger.info ("Email NOT verified");
            
            return null;
        }
    }
}

application.properties配置:

# MongoDB配置
package.mongoURI = mongodb+srv://admin:secretURL/?retryWrites=true&w=majority
问题根因

出现该问题的核心原因是调用getUserByAuth0ID时使用的不是Spring容器管理的Bean实例:

  • @Value注解的属性注入仅对Spring容器托管的单例Bean生效,如果你手动通过new DBConnectService()创建实例,该实例的mongoURI不会被注入,默认值就是null
  • 代码中将getUser、createUserAccount定义为静态方法,也容易诱导开发者绕开Spring Bean直接调用,导致属性丢失
  • 额外隐患:当前init方法中MongoClient定义为局部变量,方法执行完后可能被GC回收,会引发后续连接失效问题
修复方案
  1. 移除getUser、createUserAccount方法的static修饰符,所有业务方法通过Spring Bean实例调用
  2. 全项目禁止手动new DBConnectService实例,所有依赖该服务的位置通过@Autowired或构造器注入获取Spring托管的单例对象
  3. 将MongoClient定义为类成员变量,避免局部变量被GC回收导致连接中断,参考写法:
    private MongoClient mongoClient; // 提升为成员变量
    private MongoCollection<User> users; // 去掉static修饰
    private static Logger logger = LogManager.getLogger(DBConnectService.class);
    
    @Value("${package.mongoURI}")
    private String mongoURI;
    
    @PostConstruct
    public void init() {
        // 原有初始化逻辑,给this.mongoClient、this.users赋值即可
    }
    
  4. 如果确实存在静态逻辑需要调用服务,可在@PostConstruct中将注入的实例属性赋值给静态变量兜底,但优先推荐通过注入Bean的方式调用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:54:30