java Spring自定义配置注解

qcbq4gxm  于 2022-11-20  发布在  Java
关注(0)|答案(1)|浏览(198)

我正在尝试创建一个注解,以启用自定义Kafka配置来构建一个公共库。我的想法是将我所有的应用程序的Kafka配置变得简单,删除所有样板配置。
所以我想用一个注解来注解我的主应用程序类,并为Kafka侦听器和发布器做所有的配置。
但是我的配置类在spring组件之后初始化,我得到错误: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);
       });
    }
}

我不知道我怎么能把一个优先权给这个配置比另一个。

编辑:

当我使用限定符myTopicKafkaTemplate对在客户配置中注册的任何bean执行@Autowired操作时,如下所示:

@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)
brccelvz

brccelvz1#

自动配置不是这样工作的,它不能被导入,也不能像你的@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。

相关问题