21

I want to programmatically add a bean definition to an application context, but some properties of that definition are other beans from that context (I know their names). How can I do this so that those properties will be injected?

For example:

GenericBeanDefinition beanDef = new GenericBeanDefinition();
beanDef.setBeanClass(beanClass);

MutablePropertyValues values = new MutablePropertyValues();
values.addPropertyValue("intProperty", 10);
values.addPropertyValue("stringProperty", "Hello, world");
values.addPropertyValue("beanProperty", /* What should be here? */);

beanDef.setPropertyValues(values);

I'm using Spring 3.0.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186
Fixpoint
  • 9,619
  • 17
  • 59
  • 78

4 Answers4

22

Use RuntimeBeanReference:

values.addPropertyValue("beanProperty", new RuntimeBeanReference("beanName")); 
axtavt
  • 239,438
  • 41
  • 511
  • 482
  • 1
    Are there any differences with using a BeanDefinition as a property? – Fixpoint Aug 03 '10 at 09:25
  • 6
    @Shooshpanchick: `BeanDefinition` creates a new inner bean of the specified class, when `RuntimeBeanReference` creates a reference to the exisiting one. – axtavt Aug 03 '10 at 10:22
16

I would add a bean like this that has access to the applicationContext:

public class AppContextExtendingBean implements ApplicationContextAware{


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException{

        AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();

        // do it like this
        version1(beanFactory);

        // or like this
        version2(beanFactory);

    }

    // let spring create a new bean and then manipulate it (works only for singleton beans, obviously) 
    private void version1(AutowireCapableBeanFactory beanFactory){
        MyObject newBean = (MyObject) beanFactory.createBean(MyObject.class,AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
        newBean.setBar("baz");
        newBean.setFoo("foo");
        newBean.setPhleem("phleem");
        beanFactory.initializeBean(newBean, "bean1");
    }

    // create the object manually and then inject it into the spring context
    private void version2(AutowireCapableBeanFactory beanFactory){
        MyObject myObject=new MyObject("foo","phleem");
        myObject.setBar("baz");
        beanFactory.autowireBean(myObject);
        beanFactory.initializeBean(myObject, "bean2");
    }


}
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • Hi after lots of research I found your post and that worked fine. I am using version2. but tell me: using AutowireCapableBeanFactory would cost any memory leak or performances? thanks. – rayman Jul 12 '12 at 13:44
  • This solution is seems to be fine. MyObject is seems to be a prototype bean(since we are creating objects from our own every time). do we need to provide any kind of annotation like @Component or @Scope? how spring decides to create it's scope? – Mohammad Adnan Feb 21 '13 at 06:42
2

I found the solution. I have to use another BeanDefinition as a property, like this:

GenericBeanDefinition bd2 = new GenericBeanDefinition();
bd2.setBeanClass(Dependency.class);

GenericBeanDefinition bd1 = new GenericBeanDefinition();
bd1.setBeanClass(Component.class);

MutablePropertyValues values = new MutablePropertyValues();
values.addPropertyValue("dependency", bd2);

bd1.setPropertyValues(values);
Fixpoint
  • 9,619
  • 17
  • 59
  • 78
0

You can:

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • I can't use Javaconfig because I need to create these definitions dynamically. How can I use `BeanDefinitionParser`? – Fixpoint Jul 30 '10 at 09:31
  • javaconfig should do fine in all cases. Look at some implementations of BeanDefinitionParser to see how they work. (checkout the spring sources) – Bozho Jul 30 '10 at 10:02