Spring Wiring dynamic bean of generic type

时间:2018-04-20 00:37:17

标签: java spring generics autowired

Using Spring 5.0.3 to register a dynamic bean using the BeanDefinitionRegistryPostProcessor. The code looks as follows:

class MyBDRRPP implements BeanDefinitionRegistryPostProcessor {

   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
     // values - hardcoded for now
     List<String> values = Arrays.asList("1", "22", "333");
     registry.registerBeanDefinition("myDynamicBean", 
        BeanDefinitionBuilder.genericBeanDefinition(List.class, () -> values);
   }
}

// Register MyBDRRPP with ApplicationContext - not shown here

// Consumer of the dynamic bean
class MyConsumer {

   MyConsumer(@Qualifier("myDynamicBean") List<String> data) {
      // do something with data
   }
}

When the MyConsumer class gets wired, I get this exception

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.List<java.lang.String>' available: expected at least 1 bean which qualifies as autowire candidate.

If I change the constructor to use the raw list type instead, it works (no wiring issues).

MyConsumer(@Qualifier("myDynamicBean") List data) {
   // this works
}

How should I register my dynamic bean so that I can use the generic type instead? Is there a way to provide some hint to Spring about the type while registering the bean?

1 个答案:

答案 0 :(得分:0)

以下是我最终如何做到这一点:

class MyBDRRPP implements BeanDefinitionRegistryPostProcessor {

   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
     // values - hardcoded for now
     List<String> values = Arrays.asList("1", "22", "333");

     // OLD Code  
     // registry.registerBeanDefinition("myDynamicBean", BeanDefinitionBuilder.genericBeanDefinition(List.class, () -> values);

     // New Code
     RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(List.class, () -> values);
     // Add the generic info
     rootBeanDefinition.setTargetType(ResolvableType.forClassWithGenerics(List.class, String.class));
     registry.registerBeanDefinition("myDynamicBean", rootBeanDefinition);  
   }
}

现在可以在MyConsumer类中正确连接。