PDA

View Full Version : More on allowing bean factory method arguments



memelet
Dec 1st, 2008, 12:23 PM
Chris, while I understand the issues you pointed out in the other post, I have another use case for you to consider:

I have a class which maps to a prototype bean. This class requires some dependencies be injected (via constructor) and also some context specific constructor arguments. When using spring-xml I would have to create a factory bean to accept the injected dependencies, inject that factory into some clients which can then use the factories application specific factory methods to create the ultimate instance. But I would really like to do is:



@Configuraiton
public class MyConfig {

@Autowired Foo foo;
@Autowired Bar bar;

@Bean(scope=BeanDefinition.SCOPE_PROTOTYPE)
public Flobble fobble(String aValueSpecificForThePrototype) {
return new Fobble(aValueSpecificForThePrototype, foo, bar);
}
}


With the above I get the best of both worlds. I get dependency injection into my prototype while not needing to create yet another intermediate factory class.

Sure, other configs can't use the method fobble(..) without args to inject Fobble's as a dependency, but that's ok because the prototype-specific value /must/ be specified in order to create the instance.

After creating a simple test for this I find that while I cannot do



JavaConfigApplicationContext beanFactory = new JavaConfigApplicationContext();
FobbleConfig config = beanFactory.getBean(FobbleConfig.class)
...
Fobble fobble = config.fobble("value");


I can do



JavaConfigApplicationContext beanFactory = new JavaConfigApplicationContext();
FobbleConfig config = beanFactory.getBean(FobbleConfig.class)
...
Fobble fobble = beanFactory.getBean("fobble", "value")


This seems inconsistent. Either way the @Bean method /is/ declared with arguments and does the right thing. Why loose the "value" argument when calling the method directly?

(The arguments are lost by the time ConstructorResolver.instantiateUsingFactoryMethod( ) is invoked.)

memelet
Dec 3rd, 2008, 07:19 AM
It just occurred to me that JC already does exactly what I want. In the example above, all that need be done is to remove @Bean from fobble(..). The dependencies will still be autowired into MyConfig and hence available to fobble(..).

Now clients can use the typesafe method fobble(..), pass in prototype specific values yet still get the benefit of dependency injection.

Good work Chris, you really implemented this enhancement request fast ;)

Chris Beams
Dec 4th, 2008, 11:48 AM
Brilliant!