An Asynchronous AOP Advice Example

Over the past year, I have dabbled more and more with leveraging AOP in my applications,primarily for logging and caching. Recently, I needed to analyze a system for performance and determined that for some operations, there were several points where third party integrations are managed. These points slowed the request lifecyle dramatically and were targeted to be re-written using cfthread. I love a good refactoring challenge as much as the next guy, but I also love a good abstraction. Thus, the AsynchronousAroundAdvice was born. When would you use an Asynchronous Advice? Any void method where you want to "set it and forget it" is a good candidate for asynchronous invocation. In fact, since the alternative would produce unexpected results, the AsynchronousAroundAdvice is designed to invoke a method asynchronously only if the method returns void. Here's the code. <cfcomponent name="AsynchronousAroundAdvice" extends="coldspring.aop.MethodInterceptor" hint="Applies asychronous method invocation when returntype is void.">

<cfset variables.metadata = structNew()>

<cffunction name="invokeMethod" access="public" returntype="any" output="true">
<cfargument name="mi" type="coldspring.aop.MethodInvocation" required="true" />
<cfset var methodName = arguments.mi.getMethod().getMethodName()>
<cfset var target = arguments.mi.getTarget()>
<cfset var threadName = GenerateSecretKey("DESEDE")>
<cfif getReturnType(methodName,target) IS "void">
<cfthread name="#threadName#" action="run" target="#arguments.mi#">
<cfinvoke component="#target#" method="proceed"></cfinvoke>
</cfthread>
<cfelse>
<cfreturn arguments.mi.proceed()>
</cfif>
</cffunction>

<cffunction name="getReturnType" access="private" output="false" returntype="string" hint="returns the method returntype or any if not found">
<cfargument name="methodName" type="string" required="true">
<cfargument name="target" type="any" required="true">
<cfset var tempArr = []>
<cfset var i = 0>
<cfif not structKeyExists(variables.metadata,arguments.methodName)>
<cfset variables.metadata[arguments.methodName] = "any">
<cfset tempArr = GetMetadata(arguments.target).functions>
<cfloop from="1" to="#ArrayLen(tempArr)#" index="i">
<cfif (tempArr[i].name is arguments.methodName)>
<cfset variables.metadata[arguments.methodName] = tempArr[i].returntype>
</cfif>
</cfloop>
</cfif>
<cfreturn variables.metadata[arguments.methodName]>
</cffunction>

</cfcomponent>
Without going into the internals of ColdSpring AOP, the advice accepts a MethodInvocation instance, which is, for lack of a better description, a proxy to the original target method. By determining the return type for the original method, I can either safely fire the method using cfthread, or return the result. The cfthread tag accepts accepts metadata attributes and takes a deep copy of the arguments passed to that attribute. So the target="#arguments.mi#" part of the cfthread tag above enables the advice to fire completely thread safe. Note that the advice should be applied to a single target since the method returntype are cached by method name. And here's how one would wire up the ColdSpring for a fictitious Target object with a void method named "doSomething". <beans>

<bean id="AsyncAroundAdvice" class="test.AsynchronousAroundAdvice" />

<bean id="TargetAsynchronousAdvisor" class="coldspring.aop.support.NamedMethodPointcutAdvisor">
<property name="advice">
<ref bean="AsyncAroundAdvice" />
</property>
<property name="mappedNames">
<value>doSomething</value>
</property>
</bean>

<bean id="Target" class="coldspring.aop.framework.ProxyFactoryBean">
<property name="target">
<bean class="test.Target" />
</property>
<property name="interceptorNames">
<list>
<value>TargetAsynchronousAdvisor</value>
</list>
</property>
</bean>

</beans>

3 responses so far ↓

kaye - Apr 14, 2010 at 7:36 PM

informative

abbylyn - Apr 14, 2010 at 7:37 PM

I like the article

Redskins Jersey - Sep 21, 2011 at 4:21 AM

Fabregas free running, running, and he used his tactical awareness of a great help for us. Coach Guardiola said. Among the melon handsome imagination, Washington Redskins Jerseys Albert Haynesworth Jersey Brian Orakpo Jersey Chris Cooley Jersey Chris Horton Jersey Fabregas will play more events on the pitch middle midfielder role. During the Arsenal, Fabregas repeated muscle injuries. But in fact, Washington Redskins Jersey Clinton Portis Jersey Darrell Green Jersey DeAngelo Hall Jersey Devin Thomas Jersey he and Lionel Messi, as has a very strong muscles, so to adapt to the Barcelona game no problem. This makes Guardiola was very satisfied. His goal should be to go beyond the resume Harvey. Redskins Jersey Dexter Manley Jersey Mike Sellers Jersey Sammy Baugh Jersey Tim Hightower Jersey Guardiola said. Back to Barcelona, abregas is happy.

Leave a Comment

Leave this field empty: