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

Spring Boot中非Bean单例类能否获取application.properties属性?如何实现?

当然可以实现!在Spring Boot里,哪怕是非Bean的单例类,也有几种靠谱的方式读取application.properties里的配置。我给你整理了三个常用方案,从简单到进阶都有:

方案1:手动加载Properties文件(最直接)

如果你的单例类完全独立,不想依赖Spring的任何上下文,可以直接手动读取配置文件。这种方式不需要Spring容器支持,适合极简场景。

代码示例:

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class MySingleton {
    private static final MySingleton INSTANCE = new MySingleton();
    private String myCustomProperty;

    private MySingleton() {
        Properties props = new Properties();
        // 读取classpath下的application.properties
        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("application.properties")) {
            if (inputStream == null) {
                System.err.println("找不到application.properties文件");
                return;
            }
            props.load(inputStream);
            // 读取指定属性
            this.myCustomProperty = props.getProperty("my.custom.property");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static MySingleton getInstance() {
        return INSTANCE;
    }

    public String getMyCustomProperty() {
        return myCustomProperty;
    }
}

⚠️ 注意:这种方式需要自己处理IO异常,而且无法自动识别多环境配置(比如application-dev.properties),如果有环境区分需求,得自己判断加载对应文件。

方案2:借助Spring Environment对象(推荐)

如果你的单例类是在Spring应用启动后才使用,推荐用这种方式——通过Spring上下文获取Environment对象,它能自动处理多环境、属性优先级(比如系统变量、命令行参数覆盖配置文件)等问题。

首先需要一个Spring上下文持有者,用来保存ApplicationContext:

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContextHolder implements ApplicationContextAware {
    private static ApplicationContext appContext;

    @Override
    public void setApplicationContext(ApplicationContext context) {
        SpringContextHolder.appContext = context;
    }

    public static ApplicationContext getApplicationContext() {
        return appContext;
    }
}

然后你的单例类就可以通过这个持有者获取Environment:

import org.springframework.core.env.Environment;

public class MySingleton {
    private static final MySingleton INSTANCE = new MySingleton();
    private String myCustomProperty;

    private MySingleton() {
        // 确保Spring上下文已经初始化完成再调用
        Environment env = SpringContextHolder.getApplicationContext().getEnvironment();
        this.myCustomProperty = env.getProperty("my.custom.property");
        // 还可以指定默认值:env.getProperty("my.custom.property", "default-value")
    }

    public static MySingleton getInstance() {
        return INSTANCE;
    }

    public String getMyCustomProperty() {
        return myCustomProperty;
    }
}

⚠️ 注意:一定要保证单例的初始化时机是在Spring上下文完全启动之后,否则会拿到null的ApplicationContext。如果担心提前初始化,可以把属性读取逻辑延迟到第一次使用时执行。

方案3:使用@ConfigurationProperties(类型安全进阶)

如果你的配置属性比较多,想做类型安全的绑定,甚至加校验,就可以用@ConfigurationProperties来封装配置,再通过Spring上下文获取这个配置Bean。

首先创建配置类:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "my.custom") // 配置前缀
public class MyCustomConfig {
    private String property;
    private int maxCount; // 支持自动类型转换

    // getter和setter
    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }

    public int getMaxCount() {
        return maxCount;
    }

    public void setMaxCount(int maxCount) {
        this.maxCount = maxCount;
    }
}

然后单例类通过SpringContextHolder获取这个配置Bean:

public class MySingleton {
    private static final MySingleton INSTANCE = new MySingleton();
    private MyCustomConfig customConfig;

    private MySingleton() {
        this.customConfig = SpringContextHolder.getApplicationContext().getBean(MyCustomConfig.class);
    }

    public static MySingleton getInstance() {
        return INSTANCE;
    }

    public void doSomething() {
        System.out.println("读取的属性:" + customConfig.getProperty());
        System.out.println("最大计数:" + customConfig.getMaxCount());
    }
}

这种方式的优势是:自动类型转换、支持配置校验(配合@Validated)、属性分组清晰,适合复杂配置场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 21:12:52