2

I have an HashMap of myobjects which I want to loop through and declare each one of them as bean. At the end I want to choose one particular key as @primary.

Is there anyway to do this in Spring Java Config?

I can't really do this in listeners as these beans are required when context loads up. I was looking at factory beans but could not figure it out.

Any help is appreciated.

Thanks Abhi

Abhijith Prabhakar
  • 1,325
  • 3
  • 12
  • 24

1 Answers1

0

You can create a set of beans by getting a reference to ApplicationContext in one of your Java configuration classes. For example,

@Configuration
public class ServicesConfig {

    @PostConstruct
    public void onPostConstruct() {
       Map<String, MyClass> mapOfClasses = HashMap<>(); // your HashMap of objects
       AutowireCapableBeanFactory autowireCapableBeanFactory = context.getAutowireCapableBeanFactory();
       BeanDefinitionRegistry registry = (BeanDefinitionRegistry) autowireCapableBeanFactory;

       for (Map.Entry<String, MyClass> myClassEntry : mapOfClasses.entrySet()) {
         GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
         beanDefinition.setBeanClass(myClassEntry.getValue().getClass());
         beanDefinition.setAutowireCandidate(true);
         registry.registerBeanDefinition(myClassEntry.getKey(), beanDefinition);
         autowireCapableBeanFactory.autowireBeanProperties(myClassEntry,
                AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
       }
    }
}

Here MyClass is the type of your myobject and each MyClass can also have @Autowired annotations. At this point, I assume that each of these objects will be given their bean name the key of the HashMap. This objects then can be used as dependencies for other beans if you want.

Same thing can be achieved by implementing BeanDefinitionRegistryPostProcessor and overriding postProcessBeanDefinitionRegistry to register your HashMap of objects. In this method you will be able to create BeanDefinitions with BeanDefinitionBuilder.

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MyClass.class).getBeanDefinition();
beanDefinitionRegistry.registerBeanDefinition("key_of_this_object", beanDefinition);

I'm not sure if you can mark one of these beans as @Primary. But based on this post you can define your own bean resolver by extending DefaultListableBeanFactory which I haven't tested myself. As an alternative you may use @Qualifier as you already know which object is going to be the primary bean.

Hope this will help.

P.S If objects are already available to be added in to the ApplicationContext, following approach would add these custom objects to ApplicationContext

ConfigurableListableBeanFactory configurableListableBeanFactory = ((ConfigurableApplicationContext)context).getBeanFactory();
configurableListableBeanFactory.registerSingleton("key_of_this_object", myClassObject);
Bunti
  • 1,730
  • 16
  • 20
  • Thank you. This works when I have a list of Class in HashMap. My requirement was slightly different in the sense I already had myClass instances in HashMap which I want to register as singleton. I ended up implementing ApplicationContextAware to get ApplicationContext and then registering instances. Thanks for your help. – Abhijith Prabhakar Mar 05 '16 at 15:06