使用FactoryBean创建泛型类型的实例时,Spring自动布线无法使用泛型类型

时间:2017-08-23 01:53:44

标签: java spring spring-mvc generics spring-boot

我正在尝试在Spring版本4.3.6中解决FactoryBean中的泛型类型。我使用FactoryBean创建bean,FactoryBean用于创建任意数量的CarClient实例。

public class CarFactoryBean<T> implements FactoryBean<CarClient<T>>{

    @Autowired
    CarClientCreationHelper cch;

    private Class<T> type;

    @Overrides
    public CarClient<T> getObject() throws Exception {
        return cch.provideCar(type);
    }

    @Override
    public Class<?> getObjectType() {
        ResolvableType resolvableType = ResolvableType.forClassWithGenerics(CarClient.class, type);
        return resolvableType.resolve();
    } 

    @Override
    public boolean isSingleton() {
        return true;
    }

    public void setType(Class<T> type) {
        this.type = type;
    }
}

我正在按以下方式注册这些bean,

public class CarClientRegistrar  implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {

    private MyBeanNameGenerator bng;

    public CarClientRegistrar(){
        this.bng = new MyBeanNameGenerator();
    }


    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //logic to obtain serviceInterface, working correctly

         AbstractBeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(CarFactoryBean.class)
            .addPropertyValue("type", serviceInterface)     
            .getBeanDefinition();

        definition.setDescription("desc");

        final String beanName = bng.generateBeanName(definition, registry);
        BeanDefinitionReaderUtils.registerBeanDefinition(new BeanDefinitionHolder(definition, beanName,
            new String[]{beanName.substring(0, beanName.lastIndexOf("/"))}), registry);

    }
}

最后,我正在AppConfig中导入CarClientRegistrar,

@Import({CarClientRegistrar.class})
public class ApplicationConfig {

}

并自动装载CarClient,

  @RestController
    @RequestMapping(value = "blah")
    public class CallsController {
        private CarClient<Ford> fb;

        @Autowired
        public CallsController(CarClient<Ford> fordBean){
           this.fb = fordBean;
        }
    }

我得到以下异常,

通过构造函数参数1表示的不满意的依赖;嵌套异常是org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有'com.empire.client.CarClient'类型的限定bean可用:期望的单个匹配bean但找到2:car1Impl,car2Impl

但是,如果我重命名,将fordBean重命名为car1Impl(这是必需的bean),它可以正常工作

 @Autowired
    public CallsController(CarClient<Ford> car1Impl){
        this.fb = fordBean;
    }

有关如何解决FactoryBean中的泛型类型的任何想法,而不依赖于bean名称(但在类型上)?

ResolvableType resolvableType = ResolvableType.forClassWithGenerics(CarClient.class, type);
        return resolvableType.resolve(); 

似乎不起作用。

提前致谢!

1 个答案:

答案 0 :(得分:1)

我通过解析CarClientRegistrar中的类型并将其作为目标类型分配给BeanDefinition来解决这个问题。

ResolvableType resolvableType = ResolvableType.forClassWithGenerics(AsyncClient.class, serviceInterface);

RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
rootBeanDefinition.setTargetType(resolvableType);
rootBeanDefinition.setBeanClass(CarFactoryBean.class);
rootBeanDefinition.getPropertyValues().add("type", serviceInterface);
rootBeanDefinition.setDescription("desc");

而不是使用GenericBeanDefinition