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
相关推荐
阿丰资源2 小时前
基于SpringBoot+MySQL的社区团购系统设计与实现(附源码+文档+数据库,直接运行)
数据库·spring boot·mysql
喜欢流萤吖~2 小时前
服务间的依赖管理:微服务的协作之道
java·微服务
invicinble2 小时前
Spring如何把bean注册到容器里
java·后端·spring
恼书:-(空寄2 小时前
静态代理与动态代理,Spring AOP底层精髓全解析
spring·动态代理·静态代理
阿丰资源2 小时前
基于SpringBoot+MySQL的网上订餐系统(附源码)
spring boot·后端·mysql
代码不加糖2 小时前
0基础搭建前后端分离项目:实现菜单与界面左右布局
java·前端·javascript·mysql·elementui·mybatis
希望永不加班2 小时前
SpringBoot 敏感数据脱敏(序列化层)
java·spring boot·后端·spring
希望永不加班2 小时前
SpringBoot 数据库索引优化:慢查询分析
java·数据库·spring boot·后端·spring
胡利光3 小时前
Harness Engineering 02|Repo Harness:让仓库对 Agent 可读
java·junit·单元测试