由于弹簧上下文的两次加载,SpringBoot无法将bean注入kafkaConumser中,即在Spring受管类之外的类中

时间:2020-02-26 07:24:03

标签: java spring-boot dependency-injection apache-kafka spring-context

我正在为我的应用程序使用spring boot starter 2.2.0.RELEASE。我有一个卡夫卡消费者。现在,我想将我的spring实体注入到我的kafka使用者中(kafka使用者不由spring容器管理)。

我尝试了ApplicationContextAware,但并没有帮助我。我在kafka使用者中将applicationContext获取为null,因此无法从spring容器中获取bean。首次设置applicationContext时正确设置,但是第二次加载上下文时将其设置为null。 以下是我的应用程序的详细信息

@SpringBootApplication
@ComponentScan({"com.xyz.config_assign.service"})
public class ConfigAssignServer {

    private static Logger log = LoggerFactory.getLogger(ConfigAssignServer.class);

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigAssignServer.class, args);

        log.info("Started ConfigAssign Server!!! AppName= {} ", applicationContext.getApplicationName());

       QkafkaClient.loadConfiguration();


    }

}

我的所有应用程序类都存在于com.xyz.config_assign.service中,因此不会出现bean扫描问题。在添加Kafka用户之前,效果很好

我的ApplicationContextProvider正在使用著名的ApplicationContextAware

@Component
public class ApplicationContextProvider implements ApplicationContextAware{

    public static ApplicationContext applicationContext;


    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextProvider.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
}

现在是我的kafkaconsumer

    public class ConfigAssignmentAssetTagChangeKafkaTopicProcessor implements BatchTopicProcessor<String, String> {

    private Logger log = LoggerFactory.getLogger(ConfigAssignmentAssetTagChangeKafkaTopicProcessor.class);


    private AssignConfigServiceImpl assignConfigServiceImpl;

    public  ConfigAssignmentAssetTagChangeKafkaTopicProcessor(){
        ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
        assignConfigServiceImpl = applicationContext.getBean(AssignConfigServiceImpl.class);
    }

    @Override
    public void handleError(ConsumerRecords<String, String> arg0, Exception arg1) {
        // TODO Auto-generated method stub

    }

    @Override
    public void process(ConsumerRecords<String, String> records, long arg1) {}
}

我想为kafka消费者注入的服务是

   @Service
public class AssignConfigServiceImpl implements AssignConfigService {

    private Logger log = LoggerFactory.getLogger(AssignConfigServiceImpl.class);

    @Autowired
    private ConfigProfileDBService dbService;



    public boolean assignConfigToAgents(List<UUID> agentList, long customerId) {
        List<AgentConfigurationProfile> configProfiles = 
        dbService.getConfigurationProfilesForCustomer(customerId);
        boolean isAssignSuccessful = assignConfigToAgents(agentList, customerId, configProfiles);
        log.info("Config Assignment status ={}", isAssignSuccessful);

        return isAssignSuccessful;

    }

我使用的其他服务是

@Service
public class ConfigProfileDBService implements DBService {

    private static Logger log = LoggerFactory.getLogger(ConfigProfileDBService.class);

    @Autowired
    private JdbcTemplate jdbcTemplate;


    public List<AgentConfigurationProfile> getConfigurationProfilesForCustomer(Long customerId) {
        List<AgentConfigurationProfile> agentConfigList;
}

}

有人可以让我知道出了什么问题。我尝试了多种在线解决方案,但没有为我工作。提前致谢。 注意:我尚未使用new运算符初始化任何类。

2 个答案:

答案 0 :(得分:1)

基于问题和评论的澄清,并假设不可能将KafkaConsumer移交给Spring管理(这是我认为最好的解决方案):

@Autowired在KafkaConsumer中不起作用,因此无需放置该注释。

我假设您在此行中的应用程序上下文为空:

 ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();

这意味着在创建Kafka Consumer时尚未调用ApplicationContextProvider#setApplicationContext。除了注入,Spring还管理被管理对象的生命周期。由于您不是在春天,所以您是“自己的”,并且必须确保首先创建应用程序上下文,然后才创建其他对象(例如,像Kafka Consumer)。

当应用程序上下文启动时,它会在某个时刻一个接一个地添加bean,它还会到达ApplicationContextProvider并调用其setter。

答案 1 :(得分:0)

我的主要问题是我的spring上下文被加载了两次。当我打印每个类的类加载器时,我发现我的应用程序正在运行两次。 (即,当我按F9后在intellij中进行调试时,我又重新回到了同一行,即

ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigAssignServer.class, args);

我的问题出在pom.xml中。我从pom中删除了以下依赖项,并且有效。

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>

请检查您的依赖性。希望它能帮助某人。享受编码:)

相关问题