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
相关推荐
benbenAItalk14 小时前
数字人口播视频的批量生产实践:素材规范、任务编排与质量验收
java·前端·音视频
sunshine22 girl14 小时前
Java学习二 基本语法2, 算术运算符
java·学习
niucloud-admin15 小时前
JAVA V6 多商户商城 开发文档——插件目录结构
java·开发语言
2601_9628857215 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
滕州市燕猫虎计算机科技工作室个体工商户15 小时前
Java锁
java·开发语言
shehuiyuelaiyuehao17 小时前
1计算机是如何工作的
java·计算机网络
letisgo517 小时前
JAVA 高级进阶07篇《@Transactional失效的8个场景:代理机制到传播行为》
java·面试·transactional·spring事务·aop动态代理
水域安全老周17 小时前
水趣钓鱼救生衣专利拆解:两级锁紧如何解决落水人衣分离
java·前端·网络
三84418 小时前
Java 模板注入(FreeMarker) · 02 · 模板引擎与 FreeMarker 语法
java·开发语言·web安全·freemarker
暮雨哀尘18 小时前
Java 基础练习(一):创建类并调用对象
java·开发语言