@Autowired注入的Environment为空。

59

我在连接环境到我的Spring项目时遇到了问题。 在这个类中

@Configuration
@ComponentScan(basePackages = "my.pack.offer.*")
@PropertySource("classpath:OfferService.properties")
public class PropertiesUtil {
    @Autowired
    private Environment environment;



    @Bean
    public String load(String propertyName)
    {
        return environment.getRequiredProperty(propertyName);
    }
}

环境变量始终为空。


尝试使用@Resource而不是@Autowired。看看是否有帮助。 - Paulius Matulionis
2
@PauliusMatulionis,不,没有任何改变。 - LeYar
@LeYar 这是 PropertiesUtil 中唯一的代码吗?您是否有一个类似于 PropertySourcesPlaceholderConfigurer 的东西? - Marc-Andre
你是如何使用这个 PropertyUtil 的呢? - M. Deinum
2
在同一个基于Java的配置中同时使用@Autowired Environment和@Bean PropertyPlaceholderConfigurer会导致environment == null。实现EnvironmentAware接口可以解决这个问题。我不知道这是否是一个bug。(Spring 4.2.2) - macromaniac
5个回答

42

自动装配发生在load()被调用之后(出于某种原因)。

一种解决方法是实现 EnvironmentAware 并依赖于 Spring 调用 setEnvironment() 方法:

@Configuration
@ComponentScan(basePackages = "my.pack.offer.*")
@PropertySource("classpath:OfferService.properties")
public class PropertiesUtil implements EnvironmentAware {
    private Environment environment;

    @Override
    public void setEnvironment(final Environment environment) {
        this.environment = environment;
    }

    @Bean
    public String load(String propertyName)
    {
        return environment.getRequiredProperty(propertyName);
    }
}

2
在使用Groovy和Spock的测试环境中,无论我如何注释(Autowires、Inject、Resource),Spring都无法注入环境。按照Alex的建议实现EnvironmentAware是唯一能让它工作的方法。 - Joost den Boer

16

@Autowired替换为来自javax.annotation的@Resource,并将其设为public,例如:

@Configuration
@PropertySource("classpath:database.properties")
public class HibernateConfigurer {

    @Resource
    public Environment env;

    @Bean
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("database.driverClassName"));
        dataSource.setUrl(env.getProperty("database.url"));
        dataSource.setUsername(env.getProperty("database.username"));
        dataSource.setPassword(env.getProperty("database.password"));
        dataSource.setValidationQuery(env.getProperty("database.validationQuery"));

        return dataSource;
    }
}

您必须以这种方式在WebApplicationInitializer中注册您的configurer类

AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(ApplicationConfigurer.class); //ApplicationConfigurer imports HibernateConfigurer

对我来说它正在工作!你可能想要检查我制作的一个测试项目


我不得不将@PropertySource从我的测试类移动到配置类中。 - AmanicA

5

我使用构造函数注入解决了同样的问题:

@Configuration
@PropertySource("classpath:my.properties")
public class MyConfig {
    private Environment environment;

    public MyConfig(Environment environment) {
        this.environment = environment
    }

    @Bean
    public MyBean myBean() {
        return new MyBean(environment.getRequiredProperty("srv.name"))
    }
}

后来,我将其简化为以下形式(以便正确注入属性):

@Configuration
@PropertySource("classpath:my.properties")
public class MyConfig {
    private String serviceName;

    public MyConfig(Environment ignored) {
        /* No-op */
    }

    @Value("${srv.name}")
    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    @Bean
    public MyBean myBean() {
        return new MyBean(requireNonNull(serviceName)); // NPE without environment in constructor
    }
}

1

简洁易懂:它也可以在@PostConstruct方法中调用:

@Autowired
private Environment env;

private String appPropertyValue;

@PostConstruct
private void postConstruct() {
    this.appPropertyValue = env.getProperty("myProperty");
}

0
请将此代码放入您尝试自动装配环境的类中。
@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

问题已解决。以下是我的类代码。

@Configuration
@EnableTransactionManagement
public class DatabaseConfig {   
/**
 * DataSource definition for database connection. Settings are read from the
 * application.properties file (using the env object).
 */
@Bean
public DataSource dataSource() {

    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("db.driver"));
    dataSource.setUrl(env.getProperty("db.url"));
    dataSource.setUsername(env.getProperty("db.username"));
    dataSource.setPassword(env.getProperty("db.password"));
    return dataSource;
}

@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

  @Autowired
  private Environment env;

}

这并没有解决问题。 - gaurav kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接