Answering my own question, hopefully others will find this useful.
Using Spring.NET in a new MVC site, I noticed some peculiar behaviour. I was mainly using Spring for its AOP abilities, and to do this I make use of its IOC to create command objects. The flow is:
Controller -> ‘create’ Command object:
var ctx = ContextRegistry.GetContext();
var updateContactCommand = (IUpdateCustomerCommand) ctx["UpdateCustomerCommand"];
Controller -> set up command object with new values
Controller -> execute command object, runs Audit advice which creates an Audit row in the database with the command details
Great stuff. Or so I thought.
I have code that only set a particular field on a certain condition. But when running this, I was seeing that the database was always storing the last value that was input, across transactions, even when the condition wasn’t met. The command was remembering the value set in a previous transaction!
Of course it wasn’t remembering the value, it was simply that when Spring ‘creates’ an updateContactCommand, it was only retrieving one that was created earlier – a singleton.
This has a major impact on multi-threaded web applications! There is a possibility that separate requests, using the same command object, could result in some quite undesirable behaviour.
The default behaviour of Spring.NET is to create a singleton, and so one must add ‘singleton=”false”‘ to the end of the object declaration as below. However, because I was using AOP, my object types were declared as ProxyFactoryObjects, and singleton is not valid at this point.
The answer is still in config, and it is to use the following:
<object id="UpdateCustomerCommand" type="DataLib.Commands.UpdateCustomerCommand, DataLib" singleton="false"/>
<object type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop">
<property name="ObjectNames">
<list>
<value>UpdateCustomerCommand</value>
</list>
</property>
<property name="InterceptorNames">
<list>
<value>beforeAdvice</value>
</list>
</property>
</object>
Note the use of AutoProxy.ObjectNameAutoProxyCreator.
This indeed gives me a new instance each time, which presumably will also address the multi-threading issue – still to be tested!
Source: http://forum.springframework.net/showthread.php?7027-Lifecycle-of-objects-how-to-get-a-new-instance-for-each-call-of-GetObject()