Java 由于spring上下文的双重加载,SpringBoot无法将bean注入kafkaConumser,即在spring托管类之外的类中
我正在为我的应用程序使用spring boot starter 2.2.0.RELEASE。我有一个卡夫卡消费者。现在我想将我的spring实体注入我的kafka使用者(kafka使用者不由spring容器管理) 我尝试了ApplicationContextAware,但没有帮到我。我在kafka使用者中将applicationContext设置为null,因此无法从spring容器中获取bean。第一次正确设置applicationContext,但第二次加载上下文时将其设置为null。 以下是我申请的详细情况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。 以下
@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使用-只是一个不必要的东西,应该删除。当然,