簡體   English   中英

Spring Boot @Autowired Environment 拋出 NullPointerException

[英]Spring Boot @Autowired Environment throws NullPointerException

我有一個簡單的 SpringBoot 應用程序,我在其中使用Environment.class訪問application.properties文件下的屬性。 Environment bean 在Application.classmain方法中訪問時起作用

@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();
    }
}

當在不同的類中使用它時,它會拋出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.
}

我嘗試按照以下問題中提供的答案進行操作

Spring Boot - 環境 @Autowired 拋出 NullPointerException

自動裝配環境為空

我正在尋找解決問題的建議。

@Configuration注釋在這里被誤用於InventoryStreamingConsumer 試試@Component@Repository@Service


更新

另一個誤用是

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

@Autowired@Resource只能在Spring創建的bean工作。 您的StreamingConsumerFactory factory創建的streamingConsumer不能使用@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

首先,請只用@SpringBootApplication注釋主類

@SpringBootApplication
public class StreamingConsumerApplication {
}

@ComponentScan如果您的包與主類不在同一結構內,主類在子包外部和父包內部,而所有其他類都在父包的同一或某個子包中,則需要@ComponentScan

其次,請創建一個 Configuration 類並單獨用@Configuration對其進行注釋,並在那里為StreamingConsumer streamingConsumer定義一個@Bean ,然后它可以被@Autowired或注入InventoryStreamingConsumer類中。

第三, @Bean哪里定義的? 你確定它可以為注射自動配置嗎

第四, InventoryStreamingConsumer可以是一個@Component ,一旦上面的東西被排序,用@Autowiring注入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.
}

我有類似的問題,但從不同的文件和不同的位置讀取屬性,如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");
}
}

嘗試添加

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM