You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring中@ConfigurationProperties+@PropertySource注入值为null问题排查

问题描述

我尝试通过自定义配置文件password.properties配置Spring Bean,为避免给每个字段添加@Valid,同时使用@ConfigurationProperties(将属性值加载到字段)和@PropertySource(加载自定义配置文件),但所有字段值均为null。已生成Setter、Getter方法,也尝试添加无参和全参构造方法,问题仍未解决。

相关代码

配置类PasswordConfig

@Configuration
@EnableConfigurationProperties
@ConfigurationPropertiesScan
@PropertySource("classpath:password.properties")
@ConfigurationProperties
@Setter
@Validated
@Log4j2
public class PasswordConfig {

    @Min(1)
    private Integer minLength;
    @Min(1)
    private Integer maxLength;
    @Min(1)
    private Integer characterDigitMin;
    @Min(1)
    private Integer characterLowercaseMin;
    @Min(1)
    private Integer characterUppercaseMin;
    @Min(1)
    private Integer characterSpecialMin;

    @Bean
    public PasswordValidator passwordValidator() throws IOException {
        log.debug("Password validator [LENGTH: {}-{}, NUMBERS: {}, LOWERCASE: {}, UPPERCASE: {}, SPECIAL: {}]", minLength,
                maxLength, characterDigitMin, characterLowercaseMin, characterUppercaseMin, characterSpecialMin
        );

        return new PasswordValidator(List.of(
                new LengthRule(minLength, maxLength),
                new CharacterRule(EnglishCharacterData.Digit, characterDigitMin),
                new CharacterRule(EnglishCharacterData.LowerCase, characterLowercaseMin),
                new CharacterRule(EnglishCharacterData.UpperCase, characterUppercaseMin),
                new CharacterRule(EnglishCharacterData.Special, characterSpecialMin),
                new WhitespaceRule()
        ));
    }
}

配置文件password.properties

length.max=15
length.min=5
character.digit.min=1
character.uppercase.min=1
character.lowercase.min=1
character.special.min=1

Spring主类ReportsApplication

@SpringBootApplication
@ConfigurationPropertiesScan
public class ReportsApplication {

    public static void main(String[] args) {
        SpringApplication.run(ReportsApplication.class, args);
    }

}
错误日志
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'passwordValidator' defined in class path resource [reports/config/PasswordConfig.class]: Failed to instantiate [org.passay.PasswordValidator]: Factory method 'passwordValidator' threw exception with message: Cannot invoke "java.lang.Integer.intValue()" because the return value of "reports.config.PasswordConfig.getMinLength()" is null
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.passay.PasswordValidator]: Factory method 'passwordValidator' threw exception with message: Cannot invoke "java.lang.Integer.intValue()" because the return value of "reports.config.PasswordConfig.getMinLength()" is null

Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "reports.config.PasswordConfig.getMinLength()" is null
    at reports.config.PasswordConfig.passwordValidator(PasswordConfig.java:52) ~[classes/:na]
    at reports.config.PasswordConfig$$SpringCGLIB$$0.CGLIB$passwordValidator$11(<generated>) ~[classes/:na]
    at reports.config.PasswordConfig$$SpringCGLIB$$2.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258) ~[spring-core-6.0.12.jar:6.0.12]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-6.0.12.jar:6.0.12]
    at reports.config.PasswordConfig$$SpringCGLIB$$0.passwordValidator(<generated>) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.12.jar:6.0.12]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.0.12.jar:6.0.12]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.0.12.jar:6.0.12]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) ~[spring-aop-6.0.12.jar:6.0.12]
    at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:141) ~[spring-context-6.0.12.jar:6.0.12]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.12.jar:6.0.12]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) ~[spring-aop-6.0.12.jar:6.0.12]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703) ~[spring-aop-6.0.12.jar:6.0.12]
    at reports.config.PasswordConfig$$SpringCGLIB$$3.passwordValidator(<generated>) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:139) ~[spring-beans-6.0.12.jar:6.0.12]
    ... 25 common frames omitted


Process finished with exit code 0
已尝试的解决方法
  • 添加@NoArgsConstructor和@AllArgsConstructor注解(无效)
  • 在类上添加@EnableConfigurationProperties注解(无效)
  • 在类上添加@ConfigurationPropertiesScan注解(无效)
解决方案

问题根源在于属性绑定不匹配、配置类生命周期冲突,修改步骤如下:

  1. 拆分配置与Bean创建逻辑
    将纯属性绑定类和Bean配置类分离,确保属性绑定完成后再初始化Bean:
    纯属性类PasswordProperties
@ConfigurationProperties(prefix = "password")
@Setter
@Getter
@Validated
public class PasswordProperties {
    @Min(1)
    private Integer lengthMin;
    @Min(1)
    private Integer lengthMax;
    @Min(1)
    private Integer characterDigitMin;
    @Min(1)
    private Integer characterLowercaseMin;
    @Min(1)
    private Integer characterUppercaseMin;
    @Min(1)
    private Integer characterSpecialMin;
}

Bean配置类PasswordConfig

@Configuration
@EnableConfigurationProperties(PasswordProperties.class)
@PropertySource("classpath:password.properties")
@Log4j2
public class PasswordConfig {

    private final PasswordProperties passwordProperties;

    // 构造注入确保属性已完成绑定
    public PasswordConfig(PasswordProperties passwordProperties) {
        this.passwordProperties = passwordProperties;
    }

    @Bean
    public PasswordValidator passwordValidator() {
        log.debug("Password validator [LENGTH: {}-{}, NUMBERS: {}, LOWERCASE: {}, UPPERCASE: {}, SPECIAL: {}]", 
            passwordProperties.getLengthMin(),
            passwordProperties.getLengthMax(), 
            passwordProperties.getCharacterDigitMin(), 
            passwordProperties.getCharacterLowercaseMin(), 
            passwordProperties.getCharacterUppercaseMin(), 
            passwordProperties.getCharacterSpecialMin()
        );

        return new PasswordValidator(List.of(
                new LengthRule(passwordProperties.getLengthMin(), passwordProperties.getLengthMax()),
                new CharacterRule(EnglishCharacterData.Digit, passwordProperties.getCharacterDigitMin()),
                new CharacterRule(EnglishCharacterData.LowerCase, passwordProperties.getCharacterLowercaseMin()),
                new CharacterRule(EnglishCharacterData.UpperCase, passwordProperties.getCharacterUppercaseMin()),
                new CharacterRule(EnglishCharacterData.Special, passwordProperties.getCharacterSpecialMin()),
                new WhitespaceRule()
        ));
    }
}
  1. 调整配置文件属性前缀
    修改password.properties,为所有属性添加统一前缀,匹配@ConfigurationProperties的prefix:
password.length.min=5
password.length.max=15
password.character.digit.min=1
password.character.uppercase.min=1
password.character.lowercase.min=1
password.character.special.min=1
  1. 确保主类扫描范围正确
    主类的@ConfigurationPropertiesScan默认扫描当前包及子包,若PasswordProperties在其他包下,需指定扫描路径:
@SpringBootApplication
@ConfigurationPropertiesScan("reports.config")
public class ReportsApplication {
    public static void main(String[] args) {
        SpringApplication.run(ReportsApplication.class, args);
    }
}

内容的提问来源于stack exchange,提问作者Victor Hugo Pongolino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 00:04:54