SpringBoot не может внедрить bean-компонент в kafkaConumser, т. Е. В классе вне класса, управляемого Spring, из-за двойной загрузки контекста Spring - PullRequest
0 голосов
/ 26 февраля 2020

Я использую стартер весенней загрузки 2.2.0.RELEASE для моего приложения. У меня есть один потребитель кафки. Теперь я хочу внедрить мои пружинные сущности в моего потребителя kafka (потребитель kafka не управляется контейнером spring).

Я попробовал ApplicationContextAware, но это не помогло мне. Я получаю applicationContext как ноль в моем потребителе кафки, и, следовательно, я не могу получить бин из контейнера Spring. Первый раз applicationContext устанавливается правильно, но когда контекст загружается во второй раз, он устанавливается равным нулю. Ниже приведена краткая информация о моем приложении

@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, поэтому проблем со сканированием компонентов не возникает. Это работало хорошо, прежде чем я добавил Kafka customer

My 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 ]

1 голос
/ 26 февраля 2020

На основании уточняющих вопросов и комментариев, а также предположения, что невозможно переместить KafkaConsumer с помощью пружинного управления (что, я считаю, лучшее решение):

@Autowired не будет работать в KafkaConsumer, поэтому нет нужно поместить эту аннотацию.

Я предполагаю, что вы получаете значение NULL для контекста приложения в этой строке:

 ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();

Это означает, что ApplicationContextProvider#setApplicationContext не было вызвано к тому времени, когда вы создать Кафка Потребительская. Spring помимо инъекций также управляет жизненным циклом управляемых объектов. Поскольку вы не в весенний период, вы «сами по себе», и вы должны убедиться, что Application Context создается первым, а только после этого создавать другие объекты (например, Kafka Consumer).

Когда запускается контекст приложения, он добавляет бины один за другим в определенный момент, среди других бинов он также попадает в ApplicationContextProvider и вызывает его установщик.

0 голосов
/ 27 февраля 2020

Моя главная проблема заключалась в том, что мой весенний контекст загружался дважды. Когда я печатал загрузчик классов каждого класса, я обнаружил, что мое приложение запускалось дважды. (т.е. когда я отлаживаюсь в intellij после нажатия клавиши F9, я снова приземляюсь на той же строке, т.е.

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>

Пожалуйста, проверьте свои зависимости. Надеюсь, это кому-нибудь поможет. Наслаждайтесь кодированием:)

...