简体   繁体   English

@Value不能从application.properties插入数据

[英]@Value not inject data from application.properties

I will show you a little code and then I will ask a question. 我将向您展示一些代码,然后问一个问题。

SendEmail.java SendEmail.java

package com.goode;

import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

@Component
@NoArgsConstructor
@Data
@AllArgsConstructor
public class SendEmail {

  @Value("${email.username}")
  private String username;

  @Value("${email.password}")
  private String password;

  @Value("${email.fullAddress}")
  private String fullAddress;

  @Value("${email.host}")
  private String host;

  @Value("${email.port}")
  private String port;

  public boolean send(String toEmail, String subject, String message){
    Properties props = new Properties();
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.host", host);
    props.put("mail.smtp.port", port);

    Session session = Session.getInstance(props,
        new javax.mail.Authenticator() {
          protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(username, password);
          }
        });

    try {
      Message createMessage = new MimeMessage(session);
      createMessage.setFrom(new InternetAddress(fullAddress));
      createMessage.setRecipients(Message.RecipientType.TO,
          InternetAddress.parse(toEmail));
      createMessage.setSubject(subject);
      createMessage.setText(message);
      Transport.send(createMessage);

      return true;

    } catch (MessagingException e) {
      throw new RuntimeException(e);
    }
  }

  @Bean
  public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer()
  {
    PropertySourcesPlaceholderConfigurer o = new PropertySourcesPlaceholderConfigurer();
    o.setLocation(new ClassPathResource("application.properties"));
    return o;
  }
}

RootConfig.java RootConfig.java

package com.goode.config;

import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableJpaRepositories( basePackages = {"com.goode.repository"})
@PropertySource(value = { "classpath:application.properties" })
@EnableTransactionManagement
@Import({ SecurityConfig.class })
@ComponentScan(basePackages = {"com.goode.service", "com.goode.repository", "com.goode.controller", "com.goode.business", "com.goode"})
public class RootConfig {

  @Autowired
  private Environment environment;

  @Autowired
  private DataSource dataSource;

  @Bean
  public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
    dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
    dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
    dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));

    return dataSource;
  }

  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setDatabase(Database.POSTGRESQL);
    vendorAdapter.setGenerateDdl(true);
    vendorAdapter.setShowSql(true);

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("com.goode.business");
    factory.setDataSource(dataSource());
    factory.setJpaProperties(jpaProperties());

    return factory;
  }

  private Properties jpaProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
    properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
    return properties;
  }
  @Bean
  public PlatformTransactionManager transactionManager() {

    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(entityManagerFactory().getObject());
    return txManager;
  }

}

application.properties application.properties

jdbc.driverClassName = org.postgresql.Driver
jdbc.url = jdbc:postgresql://localhost:5432/GoodE
jdbc.username = postgres
jdbc.password = postgres
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
hibernate.show_sql = true
hibernate.format_sql = true
email.username = xx //I replce real data to xx just to this post
email.password = xx
email.fullAddress = xx@xx.com
email.host = xx
email.port = xx

When I try call a send method from SendEmail console shows error: 当我尝试从SendEmail控制台调用send方法时,显示错误:

java.lang.NullPointerException: null java.lang.NullPointerException:空

in line: 排队:

props.put("mail.smtp.host", host); props.put(“ mail.smtp.host”,host);

So annotation @Value doesn't inject any value from application.properties to private variable in SendEmail. 因此,批注@Value不会将application.properties中的任何值注入到SendEmail中的私有变量中。 Why is that? 这是为什么?

In RootConfig.java I used @Autowired , Environment and @PropertySource but I read somewhere that you can use @PropertySource only in @Configuration class so I tried find another way -> I found @Value, but I have no idea why data from application.properties are not injecting to variable. RootConfig.java中,我使用了@ AutowiredEnvironment@PropertySource,但是我读到某个地方只能在@Configuration类中使用@PropertySource,所以我尝试找到另一种方式->我找到了@Value,但是我不知道为什么来自应用程序的数据.properties不会注入变量。 I put PropertySourcesPlaceholderConfigurer in SendEmail because I read it's necessary. 我将PropertySourcesPlaceholderConfigurer放在SendEmail中,因为我读到它是必需的。 I am not sure this is the right place for it but placing this in another class eg RootConfig didn't help. 我不确定这是否合适,但是将其放在另一个类(例如RootConfig)中并没有帮助。 May you have any advice where should I search for bug? 您可能有什么建议我应该在哪里搜索错误?

This line: @PropertySource(value = { "classpath:application.properties" }) is unnecessary because all values from application.properties are picked up by default. 此行: @PropertySource(value = { "classpath:application.properties" })是不必要的,因为默认情况下会拾取来自application.properties所有值。 That being said, you also don't need PropertySourcesPlaceholderConfigurer for that. 话虽如此,您也不需要PropertySourcesPlaceholderConfigurer

Make sure that when calling your send method, that you are not instantiating your SendEmail class as new SendEmail() because that will not work as @Value works only inside of the spring application context. 请确保在调用send方法时,不要将您的SendEmail类实例化为new SendEmail()因为它将不起作用,因为@Value仅在spring应用程序上下文内部有效。

You must either do an @Autowired or constructor injection (the latter being recommended). 您必须执行@Autowired或构造函数注入(建议使用后者)。

Also this: @ComponentScan(basePackages = {"com.goode.service", "com.goode.repository", "com.goode.controller", "com.goode.business", "com.goode"}) Can be replaced by this: @ComponentScan(basePackages = {"com.goode.*"}) 还可以这样: @ComponentScan(basePackages = {"com.goode.service", "com.goode.repository", "com.goode.controller", "com.goode.business", "com.goode"})可以是替换为: @ComponentScan(basePackages = {"com.goode.*"})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM