Java 由于spring上下文的双重加载,SpringBoot无法将bean注入kafkaConumser,即在spring托管类之外的类中

Java 由于spring上下文的双重加载,SpringBoot无法将bean注入kafkaConumser,即在spring托管类之外的类中,java,spring-boot,dependency-injection,apache-kafka,spring-context,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。 以下

我正在为我的应用程序使用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扫描问题。在我添加卡夫卡消费者之前,它运行良好

我的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;
    }
}
现在我的卡夫卡消费者

    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) {}
}
公共类ConfigAssignmentAssetTagChangeKafkaTopicProcessor实现BatchTopicProcessor{
私有日志记录器log=LoggerFactory.getLogger(ConfigAssignmentAssetTagChangeKafkaTopicProcessor.class);
专用AssignConfigServiceImpl AssignConfigServiceImpl;
公共配置AssignmentAssettagChangeKafkatopicProcessor(){
ApplicationContext ApplicationContext=ApplicationContextProvider.getApplicationContext();
assignConfigServiceImpl=applicationContext.getBean(assignConfigServiceImpl.class);
}
@凌驾
公共无效句柄错误(用户记录arg0,异常arg1){
//TODO自动生成的方法存根
}
@凌驾
公共作废进程(消费者记录记录,长arg1){}
}
我想注入卡夫卡消费者的服务是

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

    }
@服务
公共类AssignConfigServiceImpl实现AssignConfigService{
专用记录器log=LoggerFactory.getLogger(AssignConfigServiceImpl.class);
@自动连线
专用配置文件数据库服务数据库服务;
公共布尔赋值配置代理(列表代理列表,长customerId){
列表配置配置文件=
dbService.getConfigurationProfilesForCustomer(customerId);
布尔值isAssignSuccessful=AssignConfigToAgent(代理列表、客户ID、配置配置文件);
info(“配置分配状态={}”,isAssignSuccessful);
返回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;
}
@服务
公共类ConfigProfileDBService实现DBService{
私有静态记录器log=LoggerFactory.getLogger(ConfigProfileDBService.class);
@自动连线
私有JdbcTemplate JdbcTemplate;
公共列表getConfigurationProfilesForCustomer(长customerId){
列表代理配置文件;
}
}

有人能告诉我哪里出了问题,我尝试了多种在线解决方案,但对我无效。提前谢谢。
注意:我没有使用new操作符初始化任何类。

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

@Autowired
在KafkaConsumer中不起作用,因此无需添加该注释

我假设这一行中的应用程序上下文为null:

 ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
这意味着在您创建Kafka Consumer时,
ApplicationContextProvider\setApplicationContext
尚未被调用。除了注入之外,Spring还管理托管对象的生命周期。因为您不在Spring中,所以您“靠自己”您必须确保首先创建应用程序上下文,并且只有在创建其他对象(例如Kafka Consumer)之后才创建应用程序上下文


当应用程序上下文启动时,它会在某个点逐个添加bean,在其他bean中,它还会访问
ApplicationContextProvider
并调用其setter。

我的主要问题是我的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>

org.springframework.boot
SpringBootStarterWeb
org.springframework.boot
弹簧靴开发工具
运行时

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

根据定义,“由spring管理的上下文”主要是:依赖项注入工作的一组bean…对象“脱离上下文”是的,但是我们可以在spring管理的实体之外使用SpringBean(我提到了几个链接),你能澄清一下什么是“它到现在还不起作用”吗-您是否遇到异常?如果是,请添加到问题中。另外,如果您可以解释为什么不将kafka consumer移动到spring管理(从问题中,我了解您无法做到这一点,因此您需要针对应用程序上下文使用静态持有者进行黑客攻击)?我这样问是因为可能有其他的解决办法可以由community@MarkBramnik我在我的卡夫卡中将applicationContext设置为nullconsumer@datta:如果你有任何对象的引用,你可以在任何地方使用它。作为一个“Springbean”意味着spring创建了这个对象。无论是谁创建了一个对象(获取调用
new
)可以初始化它(即注入东西)。Spring没有(也不能)神奇地截获所有Java
新的
。谢谢@Marks我调试了我的应用程序,发现ApplicationContextProvider#setApplicationContext在调用我的kafka使用者构造函数之前被调用。@Autowired已删除。仍然是同一问题。获取applicationContext为null。Thanks@Datta:
@Autowired
不是ca使用-只是一个不必要的东西,应该删除。当然,