Spring自定义配置注释



我正在尝试创建一个注释,以启用自定义Kafka配置来构建一个公共库。我对这种方法的想法是为我所有的应用程序简化kafka配置,删除所有样板配置。

所以我想用注释注释我的主应用程序类,并为kafka侦听器和发布者做所有配置。

但是我的配置类在弹簧组件后初始化,我得到错误:Consider defining a bean of type 'org.springframework.kafka.core.KafkaTemplate' in your configuration

我的注释:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(KafkaListenerConfigurationSelector.class)
public @interface CustomEnableKafka {}

我的配置选择器:

public class KafkaListenerConfigurationSelector implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{CustomKafkaAutoConfiguration.class.getName()};
}
}

最后是配置类:

@Slf4j
@Configuration
@EnableConfigurationProperties(CustomKafkaPropertiesMap.class)
@AutoConfigureBefore({KafkaAutoConfiguration.class})
@RequiredArgsConstructor
public class CustomKafkaAutoConfiguration {
//my properties comming from application.yml
private final CustomKafkaPropertiesMap propertiesMap;
private final ConfigurableListableBeanFactory configurableListableBeanFactory;
@PostConstruct
public void postProcessBeanFactory() {
// My logic to register beans
propertiesMap.forEach((configName, properties) -> {
// Configuring my factory with a bean name: myTopicKafkaProducerFactory
var producerFactory = new DefaultKafkaProducerFactory<>(senderProps(properties));
configurableListableBeanFactory.registerSingleton(configName + "KafkaProducerFactory", producerFactory);

//Configuring my kafka template with a bean name: myTopicKafkaTemplate
var kafkaTemplate = new KafkaTemplate<>(producerFactory);
configurableListableBeanFactory.registerSingleton(configName + "KafkaTemplate", kafkaTemplate);
});
}
}

我不知道怎样才能让这个配置优先于另一个配置。

编辑:

当我@Autowired时,我在客户配置中使用限定符myTopicKafkaTemplate注册的任何bean,如:

@Service
public class TestService {
@Autowired
@Qualifier("myTopicKafkaTemplate")
private KafkaTemplate<String, Object> myTopicKafkaTemplate;
}

然后我得到一个错误消息:

***************************
APPLICATION FAILED TO START
***************************
Description:
Field myTopicKafkaTemplate in com.example.demo.service.TestService required a bean of type 'org.springframework.kafka.core.KafkaTemplate' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)

自动配置不是这样工作的。它不能被导入,也不能像你的@AutoConfigureBefore({KafkaAutoConfiguration.class})那样做所有的自动配置。

考虑在META-INF/spring.factories文件中配置CustomKafkaAutoConfiguration作为条目,而不是自定义注释:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.my.project.CustomKafkaAutoConfiguration 

编辑

感谢您分享有关您的配置的更多信息!

因此,要使@Autowired工作,必须在应用程序上下文中注册具有各自名称和类型的bean定义。然而,你的CustomKafkaAutoConfiguration本身是bean,它在bean初始化阶段注册那些单例,这对于自动调用候选对象来说是晚的。

考虑实现ImportBeanDefinitionRegistrar而不是@PostConstruct。它不能再做@Configuration,也不能做@EnableConfigurationProperties。您可以将其移动到单独的@Configuration类中,但是在ImportBeanDefinitionRegistrar中,您必须使用EnvironmentAware-您不能从ImportBeanDefinitionRegistrar调用bean。

最新更新