Spring Boot中非Bean单例类能否获取application.properties属性?如何实现?
当然可以实现!在Spring Boot里,哪怕是非Bean的单例类,也有几种靠谱的方式读取application.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),如果有环境区分需求,得自己判断加载对应文件。
如果你的单例类是在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。如果担心提前初始化,可以把属性读取逻辑延迟到第一次使用时执行。
如果你的配置属性比较多,想做类型安全的绑定,甚至加校验,就可以用@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

