Spring配置类的演化

一.引言:一个配置失效引发的思考

java 复制代码
package com.example.demo.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Slf4j
@Component
@PropertySource(value = {"classpath:app.properties"}, ignoreResourceNotFound = true)
public class ServiceDomainConfig {
@Value("${service.domain.url}")
private String url;

@Value("${service.domain.accessKey}")
private String accessKey;

public String getUrl() {
    return url;
}

public String getAccessKey() {
    return accessKey;
}

@PostConstruct
public void init() {
    log.info("ServiceDomainConfig loading...");
    log.info("  url: {}", url == null ? "NULL" : "OK");
    log.info("  accessKey: {}", accessKey == null ? "NULL" : "OK ***");

    if (isEmpty(url)) {
        throw new IllegalArgumentException(
            "ServiceDomainConfig validation failed: service.domain.url is empty. " +
            "Please check app.properties configuration."
        );
    }
    if (isEmpty(accessKey)) {
        throw new IllegalArgumentException(
            "ServiceDomainConfig validation failed: service.domain.accessKey is empty. " +
            "Please check app.properties configuration."
        );
    }

    log.info("ServiceDomainConfig validation passed");
}

private boolean isEmpty(String value) {
    return value == null || value.trim().isEmpty();
}
}

如果在ssm项目中不配置PropertyPlaceholderConfigurer,上面的类启动便会报错,即使@PropertySource指定了配置文件也没用,因为@Value注解里面的值无法被解析。

二.SSM项目配置

正确的配置如下:

xml文件中需要配置PropertyPlaceholderConfigurer

java 复制代码
<!-- 必须手动配置 -->
<bean class="PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:app.properties"/>
</bean>

或者

java 复制代码
<!-- applicationContext.xml -->
<context:property-placeholder 
    location="classpath:app.properties" 
    ignore-resource-not-found="true"
    ignore-unresolvable="false"/>

该配置会在没找到属性资源时自动忽略对应属性。而且还可以配置从环境变量里面找值,这里就没有配置。

对应配置类如下:

java 复制代码
package com.test.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.annotation.PostConstruct;

/**
 * OSFP 通知平台配置
 *
 * @Date 2022/05/24
 * @Author linxl
 */
@Slf4j
@Configuration
@PropertySource(value = {"classpath:sys.properties"}, ignoreResourceNotFound = true)
public class OsfpApiConfig {

    @Value("${notice.url}")
    private String url;

    @Value("${notice.appid}")
    private String clientId;

    @Value("${notice.appSecret}")
    private String clientSecret;

    @Value("${notice.grantType}")
    private String grantType;

    @Value("${notice.lamsUrl}")
    private String issUrl;

    @PostConstruct
    public void init() {
        log.info("OsfpApiConfig 初始化完成 - URL: {}, ClientId: {}", url, clientId);
    }

    public String getUrl() {
        return url;
    }

    public String getClientId() {
        return clientId;
    }

    public String getClientSecret() {
        return clientSecret;
    }

    public String getGrantType() {
        return grantType;
    }

    public String getIssUrl() {
        return issUrl;
    }
}

通过这种方式便能够解析@value属性里面的值,其实@PropertySource注解也可以省略。因为通过xml的方式已经加载了对应的配置文件,并把里面的属性注入到了spring的environment里面,@Value可以正常拿到值。

三.springboot项目的配置

然而boot项目简化了许多,我们不需要配置PropertyPlaceholderConfigurer或其子类,通过下面的方式就能绑定配置文件并拿到值,而且不用加@Value注解,不用指定层级,自动可以解析相关属性。

配置类如下:

java 复制代码
package com.test.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * 通知平台配置
 *
 * @Date 2022/05/24
 * @Author linxl
 */
@Configuration
@ConfigurationProperties(prefix = "osfp")
public class OsfpApiConfig {

    String clientId;
    String clientSecret;
    String grantType;

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public String getClientSecret() {
        return clientSecret;
    }

    public void setClientSecret(String clientSecret) {
        this.clientSecret = clientSecret;
    }

    public String getGrantType() {
        return grantType;
    }

    public void setGrantType(String grantType) {
        this.grantType = grantType;
    }
}

application.xml配置文件如下:

java 复制代码
osfp:
  url: http://open-trest.sit.sf-express.com:8080
  clientId: adfcd86498d04f0ba14d5775a20c0b18
  clientSecret: bde733ffd494446794cab3e8bcc1701f
  grantType: client_credentials
相关推荐
Rain的Java大神之路7 小时前
线上接口负载满了如何解决
java·数据库·redis·后端·缓存·面试·架构
counting money8 小时前
Tomcat 专题:从基础架构到性能调优与 WebSocket 实战
java·websocket·tomcat
xiaohaiAIgeo8 小时前
【2026年】HG/T 20656-2024化工暖通空调设计规范:新版标准的变化与影响
java·前端·javascript·科普知识
小强库计算机毕业设计9 小时前
基于 Spring Boot + Vue3 的校园管理系统
java·spring boot·后端·项目实战·管理系统·技术分享·校园管理系统实战
霸道流氓气质9 小时前
Java中信号量(Semaphore):从本地到分布式
java·开发语言·分布式
怪奇云呼军9 小时前
G.711、Opus 和重采样会拖慢识别吗?闪电智能VoiceAgent 的音频入口怎么选
java·人工智能·python·算法·云计算·音视频
编程令我快乐9 小时前
maven部分构建参数讲解
java·maven
ZC跨境爬虫9 小时前
LeetCode 27. 移除元素(双指针详解 + Java Python 多解法对比)
java·python·leetcode
kisbad10 小时前
Day 036|OpenAI Agents SDK 快速开始:今天跑通第一个 Agent
java·前端·javascript
憧憬成为java架构高手的小白10 小时前
langchain4j框架学习
java