Spring Boot - @Value 注释不起作用

问题描述:

我尝试使用 SmtpAuthenticator 创建邮件服务.组件已正确启动,但用户名和密码字段中的值为空.为什么?

I try to create mail service using SmtpAuthenticator. The component is started correctly but null values are in username and password fields. Why is it?

@Component
public class SmtpAuthenticator extends Authenticator {

    private static final Logger LOG = 
    LogManager.getLogger(SmtpAuthenticator.class.getSimpleName());

    @Value("${spring.mail.username}")
    private String username;
    @Value("${spring.mail.password}")
    private String password;

    public SmtpAuthenticator() {
        LOG.info(SmtpAuthenticator.class.getSimpleName() + " started...");
        LOG.debug("username=" + username);
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
            LOG.debug("Username and password are correct...");
            return new PasswordAuthentication(username, password);
        }
    LOG.error("Not correct mail login data!");
    return null;
    }
}

你猜对了,只有在对象实例化后才会注入值;因为 spring 容器无法设置尚不存在的属性.因此,在构造函数中,这些字段仍将为空.一种解决方案是,要么

You guessed it right, the values will get injected only after the objects gets instantiated; because the spring container cannot set a property of something which doesn't exist yet. So while in constructer, those fields will still be null. One solution is, either

  1. 切换到 constructer Injection 而不是 setter Injection(YMMV,没有测试你的用例)
  1. Switch to constructer Injection instead of setter Injection (YMMV, havnt tested your usecase)

  1. @PostConstruct 注释的方法替换构造函数.这个方法会在注入过程之后执行.
  1. Replace the constructor with a method annotated with @PostConstruct. This method will be executed after the injection process.

例如

@Component
public class SmtpAuthenticator extends Authenticator {
    private static final Logger LOG = 
    LogManager.getLogger(SmtpAuthenticator.class.getSimpleName());

    @Value("${spring.mail.username}")
    private String username;
    @Value("${spring.mail.password}")
    private String password;

    @PostConstruct
    public void init() {
        LOG.info(SmtpAuthenticator.class.getSimpleName() + " started...");
        LOG.debug("username=" + username);
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
            LOG.debug("Username and password are correct...");
            return new PasswordAuthentication(username, password);
        }
    LOG.error("Not correct mail login data!");
    return null;
    }
}