kotlin Spring自动配置找不到泛型类

tkclm6bt  于 2023-11-21  发布在  Kotlin
关注(0)|答案(1)|浏览(185)

bounty将在4天后过期。回答此问题可获得+50声望奖励。Johan希望引起更多关注此问题。

我正在使用Sping Boot 3.1.5,我试图为我的一个开源项目实现一个自动配置类(称为OccurrentMongoAutoConfiguration)。在这个项目中,我有一个通用接口,如下所示:

public interface CloudEventConverter<T> {
        ... 
}

字符串
我希望自动配置创建一个默认的bean,比如interface,除非它已经存在。下面是我在自动配置类中的代码:

@Bean
@ConditionalOnMissingBean(CloudEventTypeMapper.class)
public CloudEventTypeMapper<?> occurrentTypeMapper() {
    return ReflectionCloudEventTypeMapper.qualified();
}


现在,这个CloudEventTypeMapper在这个方法中使用:

@Bean
@ConditionalOnMissingBean(CloudEventConverter.class)
public <T> CloudEventConverter<?> occurrentCloudEventConverter(Optional<ObjectMapper> objectMapper, OccurrentProperties occurrentProperties, CloudEventTypeMapper<T> cloudEventTypeMapper) {
    ObjectMapper mapper = objectMapper.orElseGet(ObjectMapper::new);
    return new JacksonCloudEventConverter.Builder<T>(mapper, occurrentProperties.getCloudEventConverter().getCloudEventSource())
            .typeMapper(cloudEventTypeMapper)
            .build();
}


然而,当我尝试引导加载自动配置的应用程序时,我得到了这个错误:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 2 of method occurrentCloudEventConverter in org.occurrent.springboot.mongo.blocking.OccurrentMongoAutoConfiguration required a bean of type 'org.occurrent.application.converter.typemapper.CloudEventTypeMapper' that could not be found.

Action:

Consider defining a bean of type 'org.occurrent.application.converter.typemapper.CloudEventTypeMapper' in your configuration.


如果我尝试手动添加这样的bean,情况也是如此:

@Bean
fun rpsTypeMapper(): CloudEventTypeMapper<GameEvent> = ReflectionCloudEventTypeMapper. qualified(GameEvent::class.java)


如果我调试代码,我可以看到它进入了rpsTypeMapper,但它似乎没有注入到occurrentCloudEventConverter(默认的occurrentTypeMapper bean也没有)。
我试过删除OccurrentMongoAutoConfiguration中的泛型(<T>),并用<?>替换它们,但没有帮助。
有什么问题,我该如何解决?
PS:这里是OccurrentMongoAutoConfiguration的代码,这里是bootstrap code。也可以通过运行TestBootstrap来使用测试容器启动应用程序。
要复制,您可以从这里克隆存储库:[[email protected]](https://stackoverflow.com/cdn-cgi/l/email-protection) :johanhaleby/occurrent.git,然后将分支切换到decider-web并在org.occurrent.example.domain.rps.decidermodel.TestBoostrap中运行main方法。

8nuwlpux

8nuwlpux1#

这个问题出现是因为Spring很坚韧确定CloudEventTypeMapper的泛型类型。
为了解决这个问题,你可以使用Spring中一个名为ResolvableType的漂亮类:

public abstract class OccurrentMongoAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(CloudEventTypeMapper.class)
    public CloudEventTypeMapper<?> occurrentTypeMapper() {
        return ReflectionCloudEventTypeMapper.qualified();
    }

    @Bean
    @ConditionalOnMissingBean(CloudEventConverter.class)
    public CloudEventConverter<?> occurrentCloudEventConverter(
            Optional<ObjectMapper> objectMapper,
            OccurrentProperties occurrentProperties,
            CloudEventTypeMapper<?> cloudEventTypeMapper) {
        
        ResolvableType resolvableType = ResolvableType.forClassWithGenerics(CloudEventConverter.class, cloudEventTypeMapper.getClass());

        ObjectMapper mapper = objectMapper.orElseGet(ObjectMapper::new);
        return new JacksonCloudEventConverter.Builder<>(mapper, occurrentProperties.getCloudEventConverter().getCloudEventSource())
                .typeMapper((CloudEventTypeMapper) resolvableType.resolveGeneric())
                .build();
    }
}

字符串
有了这个变化,Spring现在应该能够找出CloudEventTypeMapper的泛型类型,并顺利地创建occurrentCloudEventConverter bean。给予一个尝试,看看它是否能解决你的问题!

相关问题