【问题标题】:Autowired Environment is null自动连线环境为空
【发布时间】:2013-10-25 14:39:37
【问题描述】:

我在将环境连接到我的 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。看看有没有帮助。
  • @PauliusMatulionis,不,没有任何改变
  • @LeYar 这是您在PropertiesUtil 中的唯一代码吗?你有PropertySourcesPlaceholderConfigurer 或类似的吗?
  • 你是如何使用这个PropertyUtil...
  • 在相同的基于 java 的配置中使用 @Autowired Environment 和 @Bean PropertyPlaceholderConfigurer 会导致 environment == null。实现 EnvironmentAware 接口解决了这个问题。不知道是不是bug。 (春季 4.2.2)

标签: java spring properties environment autowired


【解决方案1】:

@Autowired 更改为 @Resource(来自 javax.annotation)并将其改为 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 中注册你的配置器类

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

它对我有用!您可能需要检查a test project I made

【讨论】:

  • 我不得不将 @PropertySource 从我的测试移动到我的配置类..
【解决方案2】:

自动装配发生在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);
    }
}

【讨论】:

  • 在使用 Groovy 和 Spock 的测试环境中,无论我如何注释(Autowires、Inject、Resource),Spring 都无法注入环境。按照 Alex 的建议实施 EnvironmentAware 是唯一能让这项工作发挥作用的方法。
【解决方案3】:

请将此代码放在您尝试自动装配环境的类中

@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;

}

【讨论】:

    【解决方案4】:

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

    @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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-30
      • 2016-05-25
      • 1970-01-01
      • 2021-01-13
      • 2017-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多