Spring Boot @Autowired Environment抛出NullPointerException

时间:2018-06-02 05:58:09

标签: java spring spring-boot

我有一个简单的SpringBoot应用程序,我使用Environment.class来访问application.properties文件下的属性。在Environment

main方法中访问Application.class bean时,@Configuration @EnableAutoConfiguration @ComponentScan(basePackages = "com.cisco.sdp.cdx.consumers") public class StreamingConsumerApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(StreamingConsumerApplication.class, args); Environment env = context.getBean(Environment.class); StreamingConsumerFactory factory = context.getBean(StreamingConsumerFactory.class); StreamingConsumer streamingConsumer = factory.createStreamingConsumer(StreamType.valueOf(env.getRequiredProperty("streaming.application.type"))); streamingConsumer.consume(); } } bean可以正常工作
NullPointerException

当在不同的类中使用它时,它会抛出@Configuration。我尝试使用@Component@Repository@Service@Autowired注释对该类进行注释,但无效。

我尝试了@Resource以及@Component public class InventoryStreamingConsumer implements StreamingConsumer { @Autowired private Environment env; @Autowired private JavaSparkSessionSingleton sparksession; @Autowired private StreamingContext _CONTEXT; private final Map<String, String> kafkaParams = new HashMap<String, String>(); @Override public void consume() { if(env == null) { System.out.println("ENV is NULL"); } System.out.println(env.getRequiredProperty("kafka.brokerlist")); kafkaParams.put("metadata.broker.list", env.getRequiredProperty("kafka.brokerlist")); Set<String> topics = Collections.singleton(env.getRequiredProperty("kafka.topic")); // Unrelated code. } 注释。但是,它没有用。

mjs

我尝试按照以下问题提供的答案

Spring Boot - Environment @Autowired throws NullPointerException

Autowired Environment is null

我正在寻找解决问题的建议。

4 个答案:

答案 0 :(得分:2)

这里@Configuration注释被误用InventoryStreamingConsumer。试试@Component@Repository@Service

更新

另一个误用是

StreamingConsumer streamingConsumer = factory.createStreamingConsumer(StreamType.valueOf(env.getRequiredProperty("streaming.application.type")));

@Autowired@Resource只能在bean创建的Spring中使用。 streamingConsumer创建的StreamingConsumerFactory factory无法使用@Autowired注入其属性。

您应该创建一个@Configuration课程,告诉Spring从您的工厂创建streamingConsumer。喜欢这个

@Configuration
public class ConsumerCreator {

    @Autowired
    StreamingConsumerFactory factory;

    @Bean
    public StreamingConsumer streamingConsumer() {
        return factory.createStreamingConsumer(StreamType.valueOf(env.getRequiredProperty("streaming.application.type")));
    }
}

并且不使用InventoryStreamingConsumer的注释,同时使用

        StreamingConsumer streamingConsumer = context.getBean(StreamingConsumer.class);

在您的StreamingConsumerApplication.main()方法中,而不是检索streamingConsumer

答案 1 :(得分:1)

首先,请仅使用@SpringBootApplication

注释主类
@SpringBootApplication
public class StreamingConsumerApplication {
}
如果您的包与主类不在同一个结构中,则需要

@ComponentScan,主类在子包之外,而在父包内,其中每个其他类在父包的相同或某个子包中

其次,请创建一个Configuration类并分别使用@Configuration对其进行注释,并为@Bean定义StreamingConsumer streamingConsumer,而@Autowired可以InventoryStreamingConsumer或注入@Bean {1}}上课。

第三, JavaSparkSessionSingleton InventoryStreamingConsumer在哪里定义?你确定它可以自动配置注射

第四,@Component可以是Environment,只要对上述内容进行排序,注入@Autowiring consume()就可以了。

此外,建议根据使用@Component public class InventoryStreamingConsumer implements StreamingConsumer { private final Environment env; private final JavaSparkSessionSingleton sparksession; private final StreamingContext _CONTEXT; private final Map<String, String> kafkaParams = new HashMap<String, String>(); @Autowired public InventoryStreamingConsumer(Environment env, JavaSparkSessionSingleton sparkSession, StreamingContext context) { this.env = env; this.sparksession = sparkSession; this._CONTEXT = context; } @Override public void consume() { if(env == null) { System.out.println("ENV is NULL"); } System.out.println(env.getRequiredProperty("kafka.brokerlist")); kafkaParams.put("metadata.broker.list", env.getRequiredProperty("kafka.brokerlist")); Set<String> topics = Collections.singleton(env.getRequiredProperty("kafka.topic")); // Unrelated code. } 方法的方式将您的课程更改为此。

Key        Value Value2      Min Value Min Value2
1xA         1      2            1         2
2xA         2      3            2         3
3xB         3      1            2         2
1xB         1      1            1         1
1xA         5      5            1         2
2xB         2      6            2         6
3xB         2      2            2         2
2xA         4      1            2         3

答案 2 :(得分:0)

尝试添加

@PropertySource("classpath:application.properties")
在InventoryStreamingConsumer类

这就是使用它的方式

@Configuration 
@ComponentScan({ "com.spring.config" })
@EnableTransactionManagement
@PropertySource("classpath:application.properties")
public class HibernateConfiguration {


    private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
    private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
    private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
    private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";

    @Autowired
    private Environment env;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
        dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
        dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
        dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
        return dataSource;
    }

答案 3 :(得分:0)

我有类似的问题,但是从不同的文件和不同的位置(如 common / jdbc.properties )读取属性。我这样做可以解决这个问题:

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(value = {"classpath:common/jdbc.properties"})
public class ExternalConfig implements EnvironmentAware {

private Environment environment;

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

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

public String getJdbcUrl() {
    return environment.getProperty("jdbc.url");
}
}