Java Spring Boot-Environment@Autowired抛出NullPointerException

Java Spring Boot-Environment@Autowired抛出NullPointerException,java,spring-boot,nullpointerexception,autowired,environment,Java,Spring Boot,Nullpointerexception,Autowired,Environment,我有一个使用SpringBoot0.5.0.M5的项目设置 在其中一个配置文件中,我试图@Autowire-Environment,但由于NullPointerException而失败 以下是我目前掌握的情况: Application.java @EnableAutoConfiguration @Configuration @ComponentScan public class Application { public static void main(String[] args) {

我有一个使用SpringBoot0.5.0.M5的项目设置

在其中一个配置文件中,我试图
@Autowire-Environment
,但由于
NullPointerException
而失败

以下是我目前掌握的情况:

Application.java

@EnableAutoConfiguration
@Configuration
@ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
JpaConfig.java我试图
@Autowire-Environment

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.ui.persistence.repository")
public class JpaConfig {
    private static final String DATABASE_DRIVER = "db.driver";
    private static final String DATABASE_PASSWORD = "db.password";
    private static final String DATABASE_URL = "db.url";
    private static final String DATABASE_USERNAME = "db.username";
    private static final String HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String HIBERNATE_SHOW_SQL = "hibernate.show_sql";
    private static final String ENTITYMANAGER_PACKAGES_TO_SCAN 
        = "entitymanager.packages.to.scan";

    @Autowired
    private Environment env;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty(DATABASE_DRIVER));
        dataSource.setUrl(env.getProperty(DATABASE_URL));
        dataSource.setUsername(env.getProperty(DATABASE_USERNAME));
        dataSource.setPassword(env.getProperty(DATABASE_PASSWORD));
        return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean 
                = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPersistenceProviderClass(
                HibernatePersistence.class);
        entityManagerFactoryBean.setPackagesToScan(
                env.getProperty(ENTITYMANAGER_PACKAGES_TO_SCAN));
        entityManagerFactoryBean.setJpaProperties(hibernateProperties());
        return entityManagerFactoryBean;
    }
}
我正在尝试加载属性文件中配置的数据库属性。但是,
环境
不会被注入,代码会因
NullPointerException
而失败。我没有XML文件中的任何配置

对于属性文件,我以以下方式配置了
propertysourcesplaceplaceconfigurer

@Configuration
@PropertySource("classpath:database.properties")
public class PropertyConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

我尝试过交换
@Autowired
@Resource
@Inject
,但到目前为止没有任何效果。非常感谢您的帮助。谢谢。

我相信Spring和
EntityManager Factory存在一些生命周期问题,您可能已经与这些问题发生冲突(在4.0.0.RC1中修复了)-如果您的
@Configuration
类很早就被实例化,它可能不符合自动连接的条件。您可能可以从日志输出中判断情况是否如此


出于兴趣,您是否知道,如果您使用
@EnableAutoConfiguration
(只要您
@component扫描定义存储库的包),您的
JpaConfig
PropertyConfig
提供的功能已经预先设置好了?请参见示例。

尽管您的特定问题已经解决,这里介绍了如何获取
环境
,以防Spring的自动连接发生得太晚

诀窍是实现
org.springframework.context.EnvironmentAware
;Spring然后将环境传递给
setEnvironment()
方法。 从Spring3.1开始,它就开始工作了

例如:

@Configuration
@PropertySource("classpath:myProperties.properties")
public class MyConfiguration implements EnvironmentAware {

    private Environment environment;

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

    public void myMethod() {
        final String myPropertyValue = environment.getProperty("myProperty");
        // ...
    }

}

这不像
@Autowired
@Value
那样优雅,但在某些情况下,它可以作为变通方法

我在Spring批处理中也遇到了同样的问题。写入程序无法自动连接环境类,因为配置类已在前面实例化。 所以我创建了一种单例(旧方式)来实例化环境,每次都可以访问它

我执行了以下操作:

@Configuration
@PropertySource(value = { "classpath:kid-batch.properties" }, ignoreResourceNotFound = false)
public class BatchConfiguration implements EnvironmentAware {

private static Environment env;

public static String getProperty(String key) {
    return env.getProperty(key);
}

@Override
public void setEnvironment(Environment env) {
    BatchConfiguration.env = env;
}
}


它可以工作

在spring boot应用程序中,从application.properties文件读取属性时,我遇到了类似的问题。为了解决这个问题并使它发挥作用,我做了很多努力。我终于做到了。这是我的Constants类,它将从属性文件中读取属性值。我希望这会对某人有所帮助

import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;

@Configuration
@PropertySource("classpath:application.properties")
public class Constants implements EnvironmentAware {

static Environment environment;

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

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

public static String getActiveMQHost() {
    System.out.println(environment.getProperty("spring.activemq.broker-host"));
    return environment.getProperty("spring.activemq.broker-host");
}

public static String getActiveMQPort() {
    System.out.println(environment.getProperty("spring.activemq.broker-port"));
    return environment.getProperty("spring.activemq.broker-port");
}

public static String getActiveMQUser() {
    System.out.println(environment.getProperty("spring.activemq.user"));
    return environment.getProperty("spring.activemq.user");
}

public static String getActiveMQPassword() {
    System.out.println(environment.getProperty("spring.activemq.password"));
    return environment.getProperty("spring.activemq.password");
}

}
这些是在my application.properties中声明的属性键

spring.activemq.broker-host
spring.activemq.broker-port
spring.activemq.user
spring.activemq.password

你能显示堆栈跟踪吗?另外,是否有任何东西提供了
环境
?我认为您需要一个类,该类具有一个返回标有
@Bean
的方法。此外,您可能可以使用
@Value
设置属性,而不是获取环境并以这种方式获取属性。我尝试了@Value,但没有成功。堆栈跟踪只是NullPointerException,因为尚未设置变量。谢谢。它确实很早就被调用了,在这种情况下,我需要编写代码来读取和设置属性吗?我确实看了一下它使用hsqldb的示例。我在MySQL上,我相信我需要为数据源提供连接URL、用户名等。感谢您抽出时间回复。Spring Boot有一些外部化
DataSource
configuration()的约定,所以您不需要做任何事情。如果我是你的话,在你尝试MySQL之前,我会让它与H2或HSQLDB一起工作。很酷,很有魅力(使用MySQL)!谢谢你,戴夫!我遇到了一个奇怪的情况,用配置注释的类有两个Bean方法。一个方法创建了一个数据源,另一个方法创建了一个PropertySourcesplaceConfigurer,我根据Autowired Environment字段中的值从属性文件初始化了该配置器。工作正常(在初始化configurer之前初始化了环境)。我决定将properties方法与Environment字段一起移动到另一个类中,一旦这样做了,当configurerbean初始化时,Environment就为null。使用setEnvironment()解决了这个问题。谢谢注意:这意味着你的
run
方法打印出的环境属性将在应用程序启动后执行。这是最好的答案。谢谢。