Add aspects at runtime without xml to your spring context

A user on the Spring.Net forum asked if it was possible to apply an interceptor at runtime to certain classes without resorting to xml. It turned out to be rather easy to accomplish this and encourages me to look deeper into enabling something like Fluent NHibernate for Spring.Net.

The key interface in this story is “IObjectPostProcessor”. It enables you to edit an object after it has been instantiated and populated by Spring.Net.

public interface IObjectPostProcessor
{
	object PostProcessAfterInitialization(object instance, string objectName);
 
	object PostProcessBeforeInitialization(object instance, string name);
}

The documentation states that the processors that populate entities via marker attributes should use the “PostProcessBeforeInitialization” where as postprocessors that wrap objects with proxies should use “PostProcessAfterInitialization”. In this case it’s clear that since we will create a proxy we need to implement the latter.

public object PostProcessAfterInitialization(object instance, string objectName)
{      
	if (InstanceShouldBeProxied(instance))
	{
		ProxyFactory factory = new ProxyFactory(instance);
		factory.AddAdvice(new WriteLineAspect());
		return factory.GetProxy();
	}
	return instance;
}

The implementation is rather straightforward. The postprocessor has a collection of all the types it should intercept and checks each instance it is handed. If there is a match it will create a proxyfactory, add the advice and create a proxy. Otherwise it just returns the instance.

The application context in Spring automatically picks up any processors it has and will hook it up for you. When deployed in an objectfactory however you need to explicitly register it.

The only thing left to add now is the configuration part for the postprocessor which is demonstrated in the sample below.

private static void RegisterPostProcessor(GenericApplicationContext context)
{
	MyPostProcessor postProcessor = new MyPostProcessor();
	postProcessor.InterceptInstancesOfInterface(typeof(ITaksService));
	context.ObjectFactory.AddObjectPostProcessor(postProcessor);
}

Full source code is available here: Program.cs (3.50 kb)

Leave a Reply

Your email address will not be published. Required fields are marked *