Reputation: 2596
I'm reading the Spring current version's documentation and have problems with understanding of the chapter 5.4.6 Method Injection. As far as I got we can provide the ability of recreation a bean every time we call the method using the bean. Documentation provides the following code example:
public class CommandManager implements ApplicationContextAware {
//Imports and comments were omitted
private ApplicationContext applicationContext;
public Object process(Map commandState) {
Command command = createCommand();
command.setState(commandState);
return command.execute();
}
protected Command createCommand() {
return this.applicationContext.getBean("command", Command.class);
}
public void setApplicationContext(
ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
where ApplicationContextAware
interface looks like:
public interface ApplicationContextAware {
//JavaDocs ommited
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
So, what is the method public Object process(Map commandState)
? Is it a callback? If so, where is it going to be called and who performs that call? After all, it's not clear why the bean is goign to be recreated every time it needed.
Upvotes: 0
Views: 142
Reputation: 41
According to Spring's suggestion
A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it.
solution for method get() could look like this:
public class SingletonA implements ApplicationContextAware {
private ApplicationContext applicationContext;
public PrototypeB getPrototypeB() {
return applicationContext.getBean("prototypeB",PrototypeB.class);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
with beans defenition
<bean id="singletonA" class="di.methodinjection.SingletonA" autowire="byName"/>
<bean id="prototypeB" class="di.methodinjection.PrototypeB" scope="prototype"/>
Upvotes: 0
Reputation: 20270
The Command
and CommandManager
classes are just example classes, where process()
is a part of that example. They have nothing to do with ApplicationContextAware
.
Note the comment in the example for CommandManager
:
// a class that uses a stateful Command-style class to perform some processing
process()
is to be called by the application, somewhere else; it doesn't matter for the sake of the example. If you are not using exactly the same model in your code, you should ignore this method and just call applicationContext.getBean()
where applicable.
Finally, yes CommandManager
should be registered as a bean in order for spring to call setApplicationContext()
.
edit
why does spring know that it have to recreate the bean with the name command every time
Given the contents of the example, it doesn't. The example code calls getBean()
, which, according to the javadocs:
Return an instance, which may be shared or independent, of the specified bean.
In order to ensure that you always get a new instance, you'll need to use the prototype
scope.
<bean id="beanB class="Command" scope="prototype"/>
Upvotes: 2
Reputation: 9374
Injection is happening actually here:
protected Command createCommand() {
// notice the Spring API dependency!
return this.applicationContext.getBean("command", Command.class);
}
We are just getting bean with different lifecycle in this method.
Upvotes: 1