IV. Aspect Oriented Programming w/ ColdSpring

 

IV.I. Introduction

Aspect Oriented Programming is a programming model that allows you to think about parts of an application in terms of generalized concerns, as apposed to working with a hierarchy of objects as you would in Object Oriented Programming. Although the concept may seem like a big shift in thinking, it is actually highly complementary to traditional OOP architecture. Using AOP is primarily a process of breaking apart your application into primary business concerns, those that lend themselves to traditional OOP style modeling, and generalized concerns, things like logging, security, and caching, which can be written in a abstracted, reusable manner, and then applied globally across your model with an AOP framework. Concerns like these can be thought of as aspects of your application, functionality that cuts across many of the components in your primary business logic. For this reason it's often said that AOP deals with crosscutting concerns. Working with AOP in the context of an IoC container such as ColdSpring is particularly easy and powerful, as you will primarily be dealing with programming the functionality of your aspects, and use the bean factory configuration file to configure your model components with this added functionality.

 

IV.II. Concepts

Many new technologies often come with new and sometimes confusing terminology, and AOP is certainly no exception. Below are some of the new terms you will be need to become familiar with, you may want to reference this list as you gain knowledge working with AOP.

 

Aspects: Aspects are the generalized, crosscutting concerns that you would like to apply to your model components. Your will primarily implement these aspect through the programming of Advice objects which will be joined to your model components through a process called Weaving.

 

Joinpoints: Joinpoints are areas of your application where you would like to apply your Advice objects to. Joinpoints are an abstract concept in AOP, there are no Joinpoint components that you will use, they are specific places in your model where you would like the functionality in your aspects to occur. For all intents and purposes, Joinpoints are methods in your cfcs where you will be adding functionality.

 

Pointcuts: Pointcuts are special components that you can configure to identify Joinpoints for you. Pointcuts are configured with the names of methods, which can contain the '*' wildcard character, and are the primary mechanism with which your Aspects are applied to methods in your model component.

 

Advice: Advice objects are the primary implementation of your Aspects. Working with AOP is mainly a process of adding functionality to existing methods in a cfc. You can think of this as adding advice to those methods.

 

Advisors: Advisors are special components that you configure to create pointcuts for you, and associate Advice objects with them. Advisors are used during the weaving process to build proxy objects, they are the mechanism for defining the how your Advice components should be applied to target objects.

 

Target Object: The target object is the cfc that you would like to add functionality to. ColdSpring will create a new object based on this target object that you can use in place of it elsewhere in your model.

 

Proxy Object: A proxy object is an object that ColdSpring creates to accept method calls intended for your target object, which will then look to see if there are any Advice objects to use before forwarding the method call to your target. The proxy object actually contains all the aspects and pointcuts it needs along with your target object. ColdSpring creates this object for you, which will have the same method signatures and type of your original object, making its use transparent to the rest of your model components.

 

Weaving: Weaving is the process of generating a Proxy Object, providing it with any Aspects and Pointcuts you have configured for a target object. This is performed by a ProxyBeanFactory, which is configured in your ColdSpring xml configuration file.

 

Although there are a few confusing new concepts to swallow here, it is important to understand that most of these are just that, concepts. The primary objects that you will be concerning your self with are Advice components, as they are where you will actually be writing the functionality that make up your Aspects, and Advisors, which you will define in your ColdSpring configuration file with rules that it will use to create Pointcuts for your advice. You will also configure ProxyFactoryBeans that will take care take care of building proxy objects for you (through weaving).

 

IV.III. Advice Types

ColdSpring AOP offers four types of Advice to work with. You create an advice component of one of the following types by extending a ColdSpring.aop component, and implementing a method. This allows ColdSpring to know how to use your component.

 

BeforeAdvice: BeforeAdvice components will be executed before a method that you have determined to be a Joinpoint. They have access to the method name being called, the component that the call is targeted to, and all the arguments being passed to that method. BeforeAdvice should not alter the method or arguments, as that could cause unexpected results, and possibly hard to debug exceptions.

 

AfterReturningAdvice: AfterReturningAdvice components are called after a method has completed execution and possibly returned a result. They also have access to the method, target object and arguments to the method call, as well as any returned value. Like BeforeAdvice, best practices would dictate that you should not alter the return value of a method call. If you intend to actually effect method execution in some way, you should be using the more powerful AroundAdvice.

 

AroundAdvice: AroundAdvice is a far more powerful type of advice than before or after advice, as it gives you complete control over the method execution. ColdSpring AOP implements this type of advice through the use of a component called MethodInterceptor, which in turn uses a MethodInvocation object to yield control over the method call. Although these component names probably sound strange, then are implementations of interfaces developed by a group of Java developers called the AOP Alliance, which consists of developers from the Spring Framework, Nannings Aspects, and AspectJ. These interfaces are used to provide consistency and portability between AOP implementations, and give you the benefit of having a familiarity with the concepts if you find yourself working with one of these frameworks.

 

ThrowsAdvice: ThrowsAdvice, as the name implies, are called when a method call throws an exception. You have complete access to the exception that occurred and the ability to do whatever you want with it.

 

IV.III.I BeforeAdvice

BeforeAdvice is a simple type of advice that is used to insert behavior before a method is executed. BeforeAdvice components are automatically inserted before a method call, and don't need to do anything to cause the target method to be invoked. This gives it the advantage of being very easy to use.
 
To create a before advice component, you extend the pseudo-abstract component coldspring.aop.BeforeAdvice. This will enable ColdSpring to recognize your Advice and insert it before a method call on a proxied object. To implement a before advice, you must define the following method in your component:
 
before(method, args, target)
 
Argument   Type   Description
method   coldspring.aop.Method The Method object wraps the original method call. Proceed() will automatically be called for you on the Method object after your BeforeAdvice executes (to execute the original method call )
args Struct   The argument collection that will be passed to the method call in the Method object
target   Component   The target object of the method call in the Method object (useful if your advice is very generic and needs to inspect the component that it is being applied to)
 
The coldspring.aop.Method component exposes the following methods during within before(...)
 
Method Signature Return Type Description
getMethodName() String   The name of the original method that's being called.
 
 
Example
 
The following example defines a simple logging advice to run before a method is executed. This Advice uses a LoggingService, and will interrogate the args and target arguments to send information about the method call to the LoggingService. By separating out the implementation of the actual logging, we gain the ability to easily enable/disable logging, alter the log file location, or switch implementations at will.
 
<cfcomponent name="LoggingBeforeAdvice" extends="coldspring.aop.BeforeAdvice">

<!--- setters for dependencies --->

<cffunction name="setLoggingService" returntype="void" access="public" output="false"

hint="Dependency: logging service">

<cfargument name="loggingService" type="net.klondike.service.LoggingService"

required="true"/>

<cfset variables.m_loggingService = arguments.loggingService />

</cffunction>

<cffunction name="before" access="public" returntype="any">

<cfargument name="method" type="coldspring.aop.Method" required="true" />

<cfargument name="args" type="struct" required="true" />

<cfargument name="target" type="any" required="true" />

<cfset var arg = '' />

<cfset var argString = '' />

<cfset var objName = getMetadata(arguments.target).name />

<cfloop collection="#arguments.args#" item="arg">

<cfif isSimpleValue(arguments.args[arg])>

<cfif len(argString)>

<cfset argString = argString & ', ' />

</cfif>

<cfset argString = argString & arg & '=' & arguments.args[arg] >

</cfif>

</cfloop>

<cfset variables.m_loggingService.info("[" & objName & "] "

& method.getMethodName()

& "(" & argString & ") called!") />

</cffunction>

</cfcomponent>
 
The ColdSpring bean definitions for your advice would look like this:
 
<!-- logging service -->
<bean id="loggingService" class="net.klondike.component.LoggingService" />
<!-- set up the logging advice -->
<bean id="loggingAdvice" class="net.klondike.aspects.LoggingBeforeAdvice">

<property name="loggingService">

<ref bean="loggingService" />

</property>

</bean>
 
You would then supply your advice to an advisor. The advisor is configured with either a property called "mappedName", which indicated a string pattern for which method names we want our advice applied to, or "mappedNames" which can be a comma-separated list. You can use a wildcard character ("*") in either to match multiple methods. In the example here we use mappedNames="*", which will match all methods:
 
<bean id="loggingAdvisor" class="coldspring.aop.support.NamedMethodPointcutAdvisor">

<property name="advice">

<ref bean="loggingAdvice" />

</property>

<property name="mappedNames">

<value>*</value>

</property>

</bean>
 
This advisor can configured to intercept the method calls on any object in the BeanFactory by using ProxyFactoryBean. Seen below, we set up the CatalogDAO as normal but we give it an id="catalogDAOTarget". We then create a ProxyFactoryBean with the proper id="catalogDAO". Thus anyone asking ColdSpring for the bean "catalogDAO" (or <bean/>'s that are wired to catalogDAO) get our ProxyFactoryBean, however it looks and smells like a regular catalogDAO (but in actuality has our advisor snooping method calls and applying advice as needed):
 
<!-- set up a proxy for the dao -->
<bean id="catalogDAOTarget"

class="net.klondike.component.catalogDAO">

<property name="dsn">

<value>klondike</value>

</property>

</bean>
<bean id="catalogDAO" class="coldspring.aop.framework.ProxyFactoryBean">

<property name="target">

<ref bean="catalogDAOTarget" />

</property>

<property name="interceptorNames">

<list>

<value>loggingAdvisor</value>

</list>

</property>

</bean>
 

IV.III.II AfterReturningAdvice

 
AfterReturningAdvice is used to insert behavior after a method has executed. These advice types are automatically inserted after a method is called, and although this type of advice can read any return value from the called method, it does not need to do anything to ensure normal method execution. As in BeforeAdvice, this also gives it an advantage of being simple to use.
To create an after returning advice component, you extend the pseudo-abstract component coldspring.aop.AfterReturningAdvice. This enables ColdSpring to recognize the advice and insert it after the method has executed. To implement an after retuning advice, you must define the following method in your component:
 
afterReturning(returnVal, method, args, target)
 
Argument   Type   Description
returnVal any If the method you're advising returned a value, it will be defined in the arguments scope as returnVal. If your method did not return a value returnVal will not be defined.
method   coldspring.aop.Method The Method object wraps the original method call. Proceed() will automatically be called for you on the Method object after your BeforeAdvice executes (to execute the original method call )
args Struct   The argument collection that will be passed to the method call in the Method object
target   Component   The target object of the method call in the Method object (useful if your advice is very generic and needs to inspect the component that it is being applied to)
 
The coldspring.aop.Method component exposes the following methods during within afterReturning(...)
 
Method Signature Return Type Description
getMethodName() String   The name of the original method that's being called.
 
 
Example
 
The following example defines a simple logging advice to run after a method is executed. Again, this Advice uses a LoggingService, and will interrogate the returnVal, args and target arguments to send information about the method call and return value to the LoggingService.
 
<cfcomponent name="LoggingAfterAdvice" extends="coldspring.aop.AfterReturningAdvice">

<!--- setters for dependencies --->

<cffunction name="setLoggingService" returntype="void" access="public" output="false"

hint="Dependency: logging service">

<cfargument name="loggingService" type="net.klondike.service.LoggingService"

required="true"/>

<cfset variables.m_loggingService = arguments.loggingService />

</cffunction>

<cffunction name="afterReturning" access="public" returntype="any">

<cfargument name="returnVal" type="any" required="false" />

<cfargument name="method" type="coldspring.aop.Method" required="true" />

<cfargument name="args" type="struct" required="true" />

<cfargument name="target" type="any" required="true" />

<cfset var arg = '' />

<cfset var argString = '' />

<cfset var objName = getMetadata(arguments.target).name />

<cfloop collection="#arguments.args#" item="arg">

<cfif isSimpleValue(arguments.args[arg])>

<cfif len(argString)>

<cfset argString = argString & ', ' />

</cfif>

<cfset argString = argString & arg & '=' & arguments.args[arg] >

</cfif>

</cfloop>

<cfif StructKeyExists(arguments,"returnVal")

and isSimpleValue(arguments.returnVal)>

<cfset variables.m_loggingService.info("[" & objName & "] "

& method.getMethodName()

& "(" & argString & ") called! Returning: " & arguments.returnVal) />

<cfelse>

<cfset variables.m_loggingService.info("[" & objName & "] "

& method.getMethodName()

& "(" & argString & ") called!") />

</cfif>

 

</cffunction>

</cfcomponent>
 
The ColdSpring bean definitions for your advice would look like this:
 
<!-- logging service -->
<bean id="loggingService" class="net.klondike.component.LoggingService" />
<!-- set up the logging advice -->
<bean id="loggingAdvice" class="net.klondike.aspects.LoggingAfterAdvice">

<property name="loggingService">

<ref bean="loggingService" />

</property>

</bean>
 
You would then supply your advice to an advisor. The advisor is configured with either a property called "mappedName", which indicated a string pattern for which method names we want our advice applied to, or "mappedNames" which can be a comma-separated list. You can use a wildcard character ("*") in either to match multiple methods. In the example here we use mappedNames="*", which will match all methods:
 
<bean id="loggingAdvisor" class="coldspring.aop.support.NamedMethodPointcutAdvisor">

<property name="advice">

<ref bean="loggingAdvice" />

</property>

<property name="mappedNames">

<value>*</value>

</property>

</bean>
 
Same as before, this advisor can configured to intercept the method calls on any object in the BeanFactory by using ProxyFactoryBean. Seen below, we set up the CatalogDAO as normal but we give it an id="catalogDAOTarget". We then create a ProxyFactoryBean with the proper id="catalogDAO". Thus anyone asking ColdSpring for the bean "catalogDAO" (or <bean/>'s that are wired to catalogDAO) get our ProxyFactoryBean, however it looks and smells like a regular catalogDAO (but in actuality has our advisor snooping returning method calls and applying advice as needed):
 
<!-- set up a proxy for the dao -->
<bean id="catalogDAOTarget"

class="net.klondike.component.catalogDAO">

<property name="dsn">

<value>klondike</value>

</property>

</bean>
<bean id="catalogDAO" class="coldspring.aop.framework.ProxyFactoryBean">

<property name="target">

<ref bean="catalogDAOTarget" />

</property>

<property name="interceptorNames">

<list>

<value>loggingAdvisor</value>

</list>

</property>

</bean>
 
 

IV.III.III AroundAdvice aka MethodInterceptor

Where BeforeAdvice and AfterAdvice give you're the ability to inject functionality either before or after method execution, AroundAdvice gives you both total control over and responsibility for method invocation. In around advice you are given a command object called a MethodInvocation which not only gives you access to the method name, target object, and arguments to the method call, but also access to the proceed() method of the MethodInvocation command object containing the method call. It is actually your responsibility to call proceed(), or the method call you are advising will not execute at all. For this reason, AroundAdvice is considerably more powerful than before or after advice.
 
AroundAdvice is implemented through a component called MethodInterceptor, as it gives you the ability to do just that, intercept a method call, and perform any operation necessary. When ColdSpring finds a MethodInterceptor for a method, it will relinquish all control to that object, and provide it with a MethodInvocation object, which will be used to interrogate the method call, and then trigger it's operation. Because Advice components can be chained together, it is worth noting that the object that receives the call to proceed() may not actually be the target method, it may be another MethodInterceptor. Although the internal processing may seem quite complex, the MethodInvocation object is built with all the necessary information to make this transparent to the user. It's important to realize that the MethodInterceptor is responsible for returning whatever needs to be returned from the actual method call - perhaps it's just whatever is returned from proceed(), or a completely different value all together.
 
To create a MethodInterceptor, you will extend the pseudo-abstract component coldspring.aop.MethodInterceptor. This will enable ColdSpring to recognize your advice and add it to the Advice chain used internally by the MethodInvocation object. To implement a MethodInterceptor, you must define the following method in your component:
 
invokeMethod(methodInvocation)
 
Argument   Type   Description
methodInvocation coldspring.aop.MethodInvocation The MethodInvocation object (described in detail below) gives you access to the method name, target object, and argument collection, as well as control over method execution through the proceed() method
 
 
The methodInvocation component exposes the following methods:
 
Method Return Type Description
proceed() void Invokes the next MethodInterceptor or the target method.
getMethod() coldspring.aop.Method Returnes the Method object containing the target method.
getArguments() struct Returns the argument collection from the original method call.
getTarget() Component Returnes the target object for the method call
 
 
The coldspring.aop.Method component exposes the following methods:
 
Method Signature Return Type Description
getMethodName() String   The name of the original method that's being called.
 
 
Example
 
The following example defines a simple logging advice to run as method interceptor. As you can see, the advice calls proceed() on the MethodInvocation object, and inspect the return value for logging purposes.
 
<cfcomponent name="LoggingAroundAdvice" extends="coldspring.aop.MethodInterceptor">

<!--- setters for dependencies --->

<cffunction name="setLoggingService" returntype="void" access="public" output="false"

hint="Dependency: logging service">

<cfargument name="loggingService" type="net.klondike.service.LoggingService"

required="true"/>

<cfset variables.m_loggingService = arguments.loggingService />

</cffunction>

<cffunction name="invokeMethod" access="public" returntype="any">

<cfargument name="methodInvocation" type="coldspring.aop.MethodInvocation"

required="false" />

 

<cfset var arg = '' />

<cfset var argString = '' />

 

<cfset var args = arguments.methodInvocation.getArguments() />

<cfset var methodName = arguments.methodInvocation.getMethod().getMethodName() />

<cfset var objName = getMetadata(arguments.methodInvocation.getTarget()).name />

 

<cfloop collection="#args#" item="arg">

<cfif isSimpleValue(args[arg])>

<cfif len(argString)>

<cfset argString = argString & ', ' />

</cfif>

<cfset argString = argString & arg & '=' & args[arg] >

</cfif>

</cfloop>

 

<cfset rtn = arguments.methodInvocation.proceed() />

 

<cfif isDefined('rtn') and isSimpleValue('rtn')>

<cfset variables.m_loggingService.info("[" & objName & "] "

& methodName & "(" & argString & ") complete! Returning: " & 'rtn') />

<cfelse>

<cfset variables.m_loggingService.info("[" & objName & "] "

& methodName & "(" & argString & ") complete!") />

</cfif>

 

<cfif isDefined('rtn')>

<cfreturn rtn />

</cfif>

 

</cffunction>

</cfcomponent>
 
The ColdSpring bean definitions for your MethodInterceptor would look like this:
 
<!-- logging service -->
<bean id="loggingService" class="net.klondike.component.LoggingService" />
<!-- set up the logging advice -->
<bean id="loggingAdvice" class="net.klondike.aspects.LoggingAroundAdvice">

<property name="loggingService">

<ref bean="loggingService" />

</property>

</bean>
 
You would then supply your advice to an advisor. The advisor is configured with either a property called "mappedName", which indicated a string pattern for which method names we want our advice applied to, or "mappedNames" which can be a comma-separated list. You can use a wildcard character ("*") in either to match multiple methods. In the example here we use mappedNames="*", which will match all methods:
 
<bean id="loggingAdvisor" class="coldspring.aop.support.NamedMethodPointcutAdvisor">

<property name="advice">

<ref bean="loggingAdvice" />

</property>

<property name="mappedNames">

<value>*</value>

</property>

</bean>
 
Same as before, this advisor can configured to intercept the method calls on any object in the BeanFactory by using ProxyFactoryBean. Seen below, we set up the CatalogDAO as normal but we give it an id="catalogDAOTarget". We then create a ProxyFactoryBean with the proper id="catalogDAO". Thus anyone asking ColdSpring for the bean "catalogDAO" (or <bean/>'s that are wired to catalogDAO) get our ProxyFactoryBean, however it looks and smells like a regular catalogDAO (but in actuality has our advisor snooping method calls and applying our MethodInterceptor as needed):
 
<!-- set up a proxy for the dao -->
<bean id="catalogDAOTarget"

class="net.klondike.component.catalogDAO">

<property name="dsn">

<value>klondike</value>

</property>

</bean>
<bean id="catalogDAO" class="coldspring.aop.framework.ProxyFactoryBean">

<property name="target">

<ref bean="catalogDAOTarget" />

</property>

<property name="interceptorNames">

<list>

<value>loggingAdvisor</value>

</list>

</property>

</bean>
 

IV.III.IV ThrowsAdvice

ThrowsAdvice is another simple type of advice that is used to insert behavior when method execution throws an exception. ColdSpring's AOP framework will gather the details of the exception and pass them to your advice. It's important to note that you cannot suppress the exception unless you throw a different one (if you want that level of control you may want to use AroundAdvice).
 
To create a ThrowsAdvice component, you extend the pseudo-abstract component coldspring.aop.ThrowsAdvice. This will enable ColdSpring to recognize your Advice and insert it when a method call on a proxied object throws an exception. To implement a ThrowsAdvice, you can do one of two things:
 
 
It's up to you, because you could always interrogate the exception type in a afterThrowing() method and then call the appropriate method yourself, ColdSpring just has some extra machinery to automate the mapping of exception types to methods in your advice.
 
The syntax for an afterThrowing*() method(s) are as follows
 
afterThrowing(method, args, target, exception)
 
Argument   Type   Description
method   coldspring.aop.Method The Method object wraps the original method call. Proceed() will automatically be called for you on the Method object after your BeforeAdvice executes (to execute the original method call )
args Struct   The argument collection that will be passed to the method call in the Method object
target   Component   The target object of the method call in the Method object (useful if your advice is very generic and needs to inspect the component that it is being applied to)
exception coldspring.aop.Exception A component containing the details of the exception that occurred (see below)
 
The coldspring.aop.Exception component exposes the following methods during afterThrowing*(...)
 
Method Signature Return Type Description
getType() string returns the type of the exception
getMessage() string returns the message within the exception
getDetail() string returns the detail within the exception
getTagContext() array returns an array of tags within which the exception occured
getExtendedInfo() string returns extended info, if present
getNativeErrorCode() string returns a native database error code, if present
getSqlState() string returns sqlstate, if present
getSql() string returns the sql attempting to execute, if present
getQueryError() string returns the query error, if present
getWhere() string returns the where clause of the query attempting to execute, if present
getErrNumber() string returns the database-specific error number, if present
getMissingFileName() string returns the name of a missing file, if present (exists when a template can't be found)
getLockOperation() string when getType() == "lock", returns operation that failed (Timeout, Create Mutex, or Unknown, if present
getLockName() string when getType() == "lock", returns name of affected lock (if the lock is unnamed, the value is "anonymous").
getErrorCode() string returns errorcode of exception, when present
getBaseException() cf exception (aka cfcatch) Returns the actual exception
 
The coldspring.aop.Method component exposes the following methods during afterThrowing*(...)
 
Method Signature Return Type Description
getMethodName() String   The name of the original method that's being called.
 
 
Example
 
The following example defines a simple logging advice to run when a method throws an exception. This Advice uses a LoggingService, and will interrogate the args, target, and exceptions arguments to send information about the method exception to the LoggingService. By separating out the implementation of the actual logging, we gain the ability to easily enable/disable logging, alter the log file location, or switch implementations at will.
 
<cfcomponent name="LoggingThrowsAdvice" extends="coldspring.aop.ThrowsAdvice">

<!--- setters for dependencies --->

<cffunction name="setLoggingService" returntype="void" access="public" output="false"

hint="Dependency: logging service">

<cfargument name="loggingService" type="net.klondike.service.LoggingService"

required="true"/>

<cfset variables.m_loggingService = arguments.loggingService />

</cffunction>

 

<cffunction name="afterThrowing" access="public" returntype="any">

<cfargument name="method" type="coldspring.aop.Method" required="true" />

<cfargument name="args" type="struct" required="true" />

<cfargument name="target" type="any" required="true" />

<cfargument name="exception" type="coldspring.aop.Method" required="true" />

 

<cfset var arg = '' />

<cfset var argString = '' />

<cfset var objName = getMetadata(arguments.target).name />

<cfloop collection="#arguments.args#" item="arg">

<cfif isSimpleValue(arguments.args[arg])>

<cfif len(argString)>

<cfset argString = argString & ', ' />

</cfif>

<cfset argString = argString & arg & '=' & arguments.args[arg] >

</cfif>

</cfloop>

<cfset variables.m_loggingService.info("[" & objName & "] "

& method.getMethodName()

& "(" & argString & ") threw an exception:

& arguments.exception.getType()

& "(" & arguments.exception.getMessage()

& "|" & arguments.exception.getDetail() & ")" />

</cffunction>

</cfcomponent>
 
The ColdSpring bean definitions for your advice would look like this:
 
<!-- logging service -->
<bean id="loggingService" class="net.klondike.component.LoggingService" />
<!-- set up the logging advice -->
<bean id="loggingAdvice" class="net.klondike.aspects.LoggingThrowsAdvice">

<property name="loggingService">

<ref bean="loggingService" />

</property>

</bean>
 
You would then supply your advice to an advisor. The advisor is configured with either a property called "mappedName", which indicated a string pattern for which method names we want our advice applied to, or "mappedNames" which can be a comma-separated list. You can use a wildcard character ("*") in either to match multiple methods. In the example here we use mappedNames="*", which will match all methods:
 
<bean id="loggingAdvisor" class="coldspring.aop.support.NamedMethodPointcutAdvisor">

<property name="advice">

<ref bean="loggingAdvice" />

</property>

<property name="mappedNames">

<value>*</value>

</property>

</bean>
 
This advisor can configured to intercept the method calls on any object in the BeanFactory by using ProxyFactoryBean. Seen below, we set up the CatalogDAO as normal but we give it an id="catalogDAOTarget". We then create a ProxyFactoryBean with the proper id="catalogDAO". Thus anyone asking ColdSpring for the bean "catalogDAO" (or <bean/>'s that are wired to catalogDAO) get our ProxyFactoryBean, however it looks and smells like a regular catalogDAO (but in actuality has our advisor snooping method calls and applying advice as needed (when exceptions occur)):
 
<!-- set up a proxy for the dao -->
<bean id="catalogDAOTarget"

class="net.klondike.component.catalogDAO">

<property name="dsn">

<value>klondike</value>

</property>

</bean>
<bean id="catalogDAO" class="coldspring.aop.framework.ProxyFactoryBean">

<property name="target">

<ref bean="catalogDAOTarget" />

</property>

<property name="interceptorNames">

<list>

<value>loggingAdvisor</value>

</list>

</property>

</bean>