簡體   English   中英

使用驗證程序Bean時,Spring Boot Autowired配置僅為空

[英]Spring Boot Autowired Configuration Only Null When Validator Bean Used

我有一個Spring Boot Configuration類,如下所示:

package foo.bar;

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

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

@Configuration @ConfigurationProperties(prefix = "myConfig") public class MyConfig
{

    private String foo;
    private int myValue;

    @NotNull private String requiredString;

    @Min(0) @Max(100) private int smallPositiveInt;

    public void setFoo(String foo) { this.foo = foo; }

    public void setMyValue(int myValue) { this.myValue = myValue; }

    public void setRequiredString(String requiredString) { this.requiredString = requiredString; }

    public void setSmallPositiveInt(int smallPositiveInt)
    {
        this.smallPositiveInt = smallPositiveInt;
    }

    public String getRequiredString() { return requiredString; }

    public int getSmallPositiveInt() { return smallPositiveInt; }

    public String getFoo() { return foo; }

    public int getMyValue() { return myValue; }
}

還有一個YAML配置文件,如下所示:

server:
  port: 0

myConfig:
  myValue: 9876543
  foo: Goodbye
  requiredString: Here
---

我的SpringApplication代碼如下所示:

package foo.bar;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication public class MyService implements ApplicationRunner
{

    // Define the logger object for this class
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired private MyConfig myConfig;

    // myConfig is null when I uncomment these lines:
    //    @Bean
    //    public Validator configurationPropertiesValidator()
    //    {
    //        return new MyConfigValidator();
    //    }

    @Autowired ApplicationContext applicationContext;

    @Override public void run(ApplicationArguments applicationArguments) throws Exception
    {
        log.info("Running application...");

        log.info("MyConfig values:");
        log.info("foo=" + myConfig.getFoo());
        log.info("myValue=" + myConfig.getMyValue());
        log.info("smallPositiveInt=" + myConfig.getSmallPositiveInt());

        log.warn("Example warning log message.");
        log.error("Example error log message.");
        log.debug("Example debug log message.");
    }

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

當我取消對驗證程序的注釋時,自動裝配的配置為null,但是在注釋掉它時,它的工作正常。 任何想法依賴注入會發生什么?

MyConfigValidator現在完全空白,僅實現了Validator,沒有任何實際功能,如果有人認為這可能是問題,我可以發布它。

更新:調試代碼時,我可以看到在MyConfigValidator中正在使用具有來自YAML文件的正確值的MyConfig對象調用validate()。 當對象作為Bean包含在代碼中時,Spring是否可以通過Spring Boot Application將其注入MyConfigValidator中?

更新2:在查看Spring Boot屬性驗證示例后,我能夠通過創建實現ApplicationRunner的靜態類來使其工作。 但是,我不明白為什么這樣做是必要的,並且希望避免這樣做。

我認為myConfig為null的原因是, configurationPropertiesValidator會提前實例化。 這導致MyServiceAutowiredAnnotationBeanPostProcessor可用於插入字段之前被實例化。

如果將configurationPropertiesValidator()方法設為靜態,則一切正常:

@SpringBootApplication 
public class MyService implements ApplicationRunner {

    // ...

    @Bean
    public static Validator configurationPropertiesValidator() {
        return new MyConfigValidator();
    }

    // ...

}

對於我的項目而言,最有效的方法是將驗證器嵌入到配置類中,如下所示:

@Component 
@ConfigurationProperties(prefix = "myConfig") 
public class MyConfig implements Validator
{

private String foo;
private int myValue;
private String requiredString;
private int smallPositiveInt;

private final Logger log = LoggerFactory.getLogger(this.getClass());

// This means that this validator only supports validating configs of type "MyConfig".
@Override public boolean supports(Class<?> type) { return type == MyConfig.class; }

@Override public void validate(Object o, Errors errors)
{
    MyConfig c = (MyConfig)o;
    log.info("Validating: " + c.toString());
    if(c.getSmallPositiveInt() == 60)
    {
        errors.rejectValue("smallPositiveInt", "error", "Cannot be 60!");
    }
}
}

請讓我知道使用這種方法的任何弊端,當使用多個配置對象時,它似乎是最好的解決方案,因為只要通過Spring依賴注入創建它們,它們似乎都會得到驗證。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM