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
相关推荐
largecode18 小时前
如何让电话显示店名?来电显示店铺名称,提升有效接通率
java·开发语言·spring·百度·学习方法·业界资讯·twitter
xuhaoyu_cpp_java18 小时前
SpringMVC学习(五)
java·开发语言·经验分享·笔记·学习·spring
计算机安禾18 小时前
【c++面向对象编程】第22篇:输入输出运算符重载:<< 与 >> 的友元实现
java·前端·c++
HLAIA光子18 小时前
这些Spring Boot写法已经过时了!
spring boot·后端
旷世奇才李先生18 小时前
Java虚拟线程原理与实践
java
heimeiyingwang18 小时前
【架构实战】RPC框架Dubbo3.0:高性能Java通信之道
java·rpc·架构
i220818 Faiz Ul18 小时前
宠物猫之猫咖管理系统|基于java + vue宠物猫之猫咖管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·宠物猫之猫咖管理系统
Nyarlathotep011318 小时前
定时线程池:ScheduledThreadPoolExecutor
java·后端
i220818 Faiz Ul19 小时前
二手交易系统|基于springboot + vue二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·二手交易系统
旷世奇才李先生19 小时前
Spring Security OAuth2完整集成方案
java