diff --git a/doc/reference/src/aop.xml b/doc/reference/src/aop.xml index 83234c43..3e7107bd 100644 --- a/doc/reference/src/aop.xml +++ b/doc/reference/src/aop.xml @@ -16,7 +16,12 @@ * limitations under the License. */ --> - + Aspect Oriented Programming with Spring.NET @@ -172,8 +177,8 @@ accomplish the same thing. Using the most specific advice type provides a simpler programming model with less potential for errors. For example, you don't need to invoke the proceed() method on the - IMethodInvocation used for around advice, and - hence can't fail to invoke it. + IMethodInvocation used for around advice, and hence + can't fail to invoke it. The pointcut concept is the key to AOP, distinguishing AOP from older technologies offering interception. Pointcuts enable advice to be @@ -205,25 +210,23 @@ an object representing an aspect, including both an advice and a pointcut targeting it to specific joinpoints. - Different advice types are - IMethodInterceptor (from the AOP Alliance - interception API); and the advice interfaces defined in the - Spring.Aop namespace. All advices must implement the - AopAlliance.Aop.IAdvice tag interface. Advices - supported out the box are IMethodInterceptor ; - IThrowsAdvice; - IBeforeAdvice; and - IAfterReturningAdvice. We'll discuss advice types + Different advice types are IMethodInterceptor + (from the AOP Alliance interception API); and the advice interfaces + defined in the Spring.Aop namespace. All advices must + implement the AopAlliance.Aop.IAdvice tag interface. + Advices supported out the box are IMethodInterceptor + ; IThrowsAdvice; IBeforeAdvice; + and IAfterReturningAdvice. We'll discuss advice types in detail below. Spring.NET provides a .NET translation of the Java interfaces defined by the - AOP Alliance. Around advice must implement - the AOP Alliance - AopAlliance.Interceptr.IMethodInterceptor - interface. Whilst there is wide support for the AOP Alliance in Java, - Spring.NET is currently the only .NET AOP framework that makes use of - these interfaces. In the short term, this will provide a consistent + AOP Alliance + . Around advice must implement the AOP Alliance + AopAlliance.Interceptr.IMethodInterceptor interface. + Whilst there is wide support for the AOP Alliance in Java, Spring.NET is + currently the only .NET AOP framework that makes use of these + interfaces. In the short term, this will provide a consistent programming model for those doing development in both .NET and Java, and in the longer term, we hope to see more .NET projects adopt the AOP Alliance interfaces. @@ -318,8 +321,8 @@ composition operations (such as performing a "union" with another method matcher). - The ITypeFilter interface is used to - restrict the pointcut to a given set of target classes. If the + The ITypeFilter interface is used to restrict + the pointcut to a given set of target classes. If the Matches() method always returns true, all target types will be matched: @@ -328,8 +331,8 @@ bool Matches(Type type); } - The IMethodMatcher interface is normally - more important. The complete interface is shown below: + The IMethodMatcher interface is normally more + important. The complete interface is shown below: public interface IMethodMatcher { @@ -346,9 +349,9 @@ avoid the need for a test on every method invocation. If the 2-argument matches method returns true for a given method, and the IsRuntime property for the - IMethodMatcher returns true, the 3-argument - matches method will be invoked on every method invocation. This enables - a pointcut to look at the arguments passed to the method invocation + IMethodMatcher returns true, the 3-argument matches + method will be invoked on every method invocation. This enables a + pointcut to look at the arguments passed to the method invocation immediately before the target advice is to execute. Most IMethodMatchers are static, meaning that @@ -441,13 +444,12 @@ As a convenience, Spring provides the - RegularExpressionMethodPointcutAdvisor class - that allows us to reference an IAdvice - instance as well as defining the pointcut rules (remember that an - IAdvice instance can be an interceptor, - before advice, throws advice etc.) This simplifies wiring, as the - one object serves as both pointcut and advisor, as shown - below: + RegularExpressionMethodPointcutAdvisor class that + allows us to reference an IAdvice instance as + well as defining the pointcut rules (remember that an + IAdvice instance can be an interceptor, before + advice, throws advice etc.) This simplifies wiring, as the one + object serves as both pointcut and advisor, as shown below: @@ -466,9 +468,8 @@ - The - RegularExpressionMethodPointcutAdvisor class - can be used with any Advice type. + The RegularExpressionMethodPointcutAdvisor + class can be used with any Advice type. If you only have one pattern you can use the property name @@ -480,19 +481,19 @@ and specifying a list. - You may also specify a Regex object - from the System.Text.RegularExpressions - namespace. The built in RegexConverter class - will perform the conversion. See for more information - on Spring's build in type converters. The Regex object is created as - any other object within the IoC container. Using an inner-object - definition for the Regex object is a handy way to keep the - definition close to the PointcutAdvisor declaration. Note that the - class SdkRegularExpressionMethodPointcut has - a DefaultOptions property to set the - regular expression options if they are not explicitly specified in - the constructor. + You may also specify a Regex object from + the System.Text.RegularExpressions namespace. The + built in RegexConverter class will perform the + conversion. See + for more information on Spring's build in type converters. The Regex + object is created as any other object within the IoC container. + Using an inner-object definition for the Regex object is a handy way + to keep the definition close to the PointcutAdvisor declaration. + Note that the class + SdkRegularExpressionMethodPointcut has a + DefaultOptions property to set the regular + expression options if they are not explicitly specified in the + constructor. @@ -506,9 +507,8 @@ configure itself. The class AttributeMatchMethodPointcut provides this functionality. Sample usage that will match all methods that have - the attribute - Spring.Attributes.CacheAttribute is shown - below. <object id="cachePointcut" type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop"> + the attribute Spring.Attributes.CacheAttribute is + shown below. <object id="cachePointcut" type="Spring.Aop.Support.AttributeMatchMethodPointcut, Spring.Aop"> <property name="Attribute" value="Spring.Attributes.CacheAttribute, Spring.Core"/> </object> @@ -528,10 +528,10 @@ information on this particular advice. As a convenience the class - AttributeMatchMethodPointcutAdvisor is - provided to defining an attribute based Advisor as a somewhat - shorter alternative to using the generic DefaultPointcutAdvisor. An - example is shown below.<object id="AspNetCacheAdvice" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop"> + AttributeMatchMethodPointcutAdvisor is provided + to defining an attribute based Advisor as a somewhat shorter + alternative to using the generic DefaultPointcutAdvisor. An example + is shown below.<object id="AspNetCacheAdvice" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop"> <property name="advice"> <object type="Aspect.AspNetCacheAdvice, Aspect"/> </property> @@ -742,8 +742,8 @@ public int GetAge(IPerson person) possibility of inadvertently failing to proceed down the interceptor chain. - The IMethodBeforeAdvice interface is - shown below. + The IMethodBeforeAdvice interface is shown + below. public interface IMethodBeforeAdvice : IBeforeAdvice { @@ -814,9 +814,9 @@ public int GetAge(IPerson person) } The following advice is invoked if a - SqlException is thrown. Unlike the above - advice, it declares 4 arguments, so that it has access to the invoked - method, method arguments and target object: + SqlException is thrown. Unlike the above advice, it + declares 4 arguments, so that it has access to the invoked method, + method arguments and target object: public class SqlExceptionThrowsAdviceWithArguments : IThrowsAdvice { @@ -828,9 +828,9 @@ public int GetAge(IPerson person) The final example illustrates how these two methods could be used in a single class, which handles both RemotingException and - SqlException. Any number of throws advice - methods can be combined in a single class, as can be seen in the - following example. + SqlException. Any number of throws advice methods + can be combined in a single class, as can be seen in the following + example. public class CombinedThrowsAdvice : IThrowsAdvice { @@ -850,24 +850,22 @@ public int GetAge(IPerson person) AfterThrowing method will only be invoked if the type of the thrown exception is RemotingException... if a - RemotingException has been thrown and - subsequently wrapped inside another exception before the exception - bubbles up to the throws advice interceptor, then the throws advice - that handles RemotingExceptions will RemotingException has been thrown and subsequently + wrapped inside another exception before the exception bubbles up to + the throws advice interceptor, then the throws advice that handles + RemotingExceptions will never be called. Consider a business method that is advised by throws advice that handles RemotingExceptions; if during the course of a method invocation said business method throws a RemoteException... and - subsequently wraps said RemotingException - inside a business-specific - BadConnectionException (see the code snippet - below) before throwing the exception, then the throws advice will - never be able to respond to the - RemotingException... because all the throws - advice sees is a BadConnectionException. The - fact that the RemotingException is wrapped up - inside the BadConnectionException is - immaterial. + subsequently wraps said RemotingException inside a + business-specific BadConnectionException (see the + code snippet below) before throwing the exception, then the throws + advice will never be able to respond to the + RemotingException... because all the throws advice + sees is a BadConnectionException. The fact that the + RemotingException is wrapped up inside the + BadConnectionException is immaterial. public void BusinessMethod() { @@ -890,8 +888,8 @@ public int GetAge(IPerson person) After Returning advice An after returning advice in Spring.NET must implement the - Spring.Aop.IAfterReturningAdvice interface, - shown below: + Spring.Aop.IAfterReturningAdvice interface, shown + below: public interface IAfterReturningAdvice : IAdvice { @@ -956,8 +954,8 @@ public int GetAge(IPerson person) declaration that implements the tag interface IAdvice. The need for implementing this marker interface will likely be removed in future versions. As - an example, consider the interface IAuditable - that describes the last modified time of an object. + an example, consider the interface IAuditable that + describes the last modified time of an object. @@ -979,15 +977,16 @@ public int GetAge(IPerson person) Access to the advised object can be obtained by implementing the - interface ITargetAware public interface ITargetAware + interface ITargetAware public interface ITargetAware { IAopProxy TargetProxy { set; } -} with the IAopProxy reference - providing a layer of indirection through which the advised object can - be accessed. public interface IAopProxy +} with the IAopProxy reference providing a + layer of indirection through which the advised object can be accessed. + public interface IAopProxy { object GetProxy(); } @@ -1036,10 +1035,9 @@ public int GetAge(IPerson person) Introduction advice is not associated with a pointcut, since it applies at the class and not the method level. As such, introductions - use their own subclass of the interface - IAdvisor, namely - IIntroductionAdvisor, to specify the types that - the introduction can be applied to. + use their own subclass of the interface IAdvisor, + namely IIntroductionAdvisor, to specify the types + that the introduction can be applied to. @@ -1072,9 +1070,9 @@ public int GetAge(IPerson person) Spring.NET provides a default implementation of this interface - (the DefaultIntroductionAdvisor class) that - should be sufficient for the majority of situations when you need to - use introductions. The most simple implementation of an introduction + (the DefaultIntroductionAdvisor class) that should + be sufficient for the majority of situations when you need to use + introductions. The most simple implementation of an introduction advisor is a subclass that simply passes a new instance the base constructor. Passing a new instance is important since we want a new instance of the mixin classed used for each advised object. @@ -1133,18 +1131,18 @@ public int GetAge(IPerson person) Apart from the special case of introductions, any advisor can be used with any advice. The - Spring.Aop.Support.DefaultPointcutAdvisor class is - the most commonly used advisor implementation. For example, it can be used + Spring.Aop.Support.DefaultPointcutAdvisor class is the + most commonly used advisor implementation. For example, it can be used with a IMethodInterceptor, - IBeforeAdvice or - IThrowsAdvice and any pointcut definition. + IBeforeAdvice or IThrowsAdvice and + any pointcut definition. Other convenience implementations provided are: AttributeMatchMethodPointcutAdvisor shown in usage previously in for use with attribute based pointcuts. - RegularExpressionMethodPointcutAdvisor that will - apply pointcuts based on the matching a regular expression to method + RegularExpressionMethodPointcutAdvisor that will apply + pointcuts based on the matching a regular expression to method names. It is possible to mix advisor and advice types in Spring.NET in the @@ -1154,14 +1152,13 @@ public int GetAge(IPerson person) - Using the ProxyFactoryObject to create - AOP proxies + Using the ProxyFactoryObject to create AOP proxies If you're using the Spring.NET IoC container for your business objects - generally a good idea - you will want to use one of Spring.NET's - AOP-specific IFactoryObject implementations - (remember that a factory object introduces a layer of indirection, - enabling it to create objects of a different type - IFactoryObject implementations (remember + that a factory object introduces a layer of indirection, enabling it to + create objects of a different type - ). The basic way to create an AOP proxy in Spring.NET is to use the @@ -1173,21 +1170,20 @@ public int GetAge(IPerson person) Basics - The ProxyFactoryObject, like other - Spring.NET IFactoryObject implementations, - introduces a level of indirection. If you define a - ProxyFactoryObject with name - foo, what objects referencing foo - see is not the ProxyFactoryObject instance - itself, but an object created by the - ProxyFactoryObject's implementation of the - GetObject() method. This method will create an AOP - proxy wrapping a target object. + The ProxyFactoryObject, like other Spring.NET + IFactoryObject implementations, introduces a level of + indirection. If you define a ProxyFactoryObject with + name foo, what objects referencing + foo see is not the + ProxyFactoryObject instance itself, but an object + created by the ProxyFactoryObject's implementation of + the GetObject() method. This method will create an + AOP proxy wrapping a target object. One of the most important benefits of using a - ProxyFactoryObject or other IoC-aware classes - that create AOP proxies, is that it means that advice and pointcuts can - also be managed by IoC. This is a powerful feature, enabling certain + ProxyFactoryObject or other IoC-aware classes that + create AOP proxies, is that it means that advice and pointcuts can also + be managed by IoC. This is a powerful feature, enabling certain approaches that are hard to achieve with other AOP frameworks. For example, an advice may itself reference application objects (besides the target, which should be available in any AOP framework), benefiting from @@ -1198,8 +1194,8 @@ public int GetAge(IPerson person) ProxyFactoryObject Properties Like most IFactoryObject implementations - provided with Spring.NET, the ProxyFactoryObject - is itself a Spring.NET configurable object. Its properties are used + provided with Spring.NET, the ProxyFactoryObject is + itself a Spring.NET configurable object. Its properties are used to: @@ -1213,9 +1209,9 @@ public int GetAge(IPerson person) Some key properties are inherited from the - Spring.Aop.Framework.ProxyConfig class: this - class is the superclass for all AOP proxy factories in Spring.NET. Some - of the key properties include: + Spring.Aop.Framework.ProxyConfig class: this class is + the superclass for all AOP proxy factories in Spring.NET. Some of the + key properties include: @@ -1283,8 +1279,8 @@ public int GetAge(IPerson person) The names are object names in the current container, including objectnames from container hierarchies. You can't mention object references here since doing so would result in the - ProxyFactoryObject ignoring the singleton - setting of the advise. + ProxyFactoryObject ignoring the singleton setting + of the advise. @@ -1456,8 +1452,7 @@ public int GetAge(IPerson person) Let's look at an example of configuring the proxy objects retrieved from ProxyFactoryObject. - - + <!-- create the object to reference --> <object id="RealObjectTarget" type="MyRealObject" singleton="false"/> <!-- create the proxied object for everyone to use--> @@ -1466,18 +1461,18 @@ public int GetAge(IPerson person) <property name="isSingleton" value="false"/> <property name="targetName" value="RealObjectTarget" /> </object> - If you are using a prototype as the target you must set the - TargetName property with the name/object id of your - object and not use the property Target with a - reference to that object. This will then allow a new proxy to be created - around a new prototype target instance. - - - Consider the above Spring.Net object configuration. Notice that the - IsSingleton property of the ProxyFactoryObject - instance is set to false. This means that each proxy object will be unique. - Thus, you can configure each proxy object with its' own individual advice(s) - using the following syntax + If you are using a prototype as the target you must + set the TargetName property with the name/object id + of your object and not use the property Target with a + reference to that object. This will then allow a new proxy to be created + around a new prototype target instance. + + Consider the above Spring.Net object configuration. Notice that + the IsSingleton property of the + ProxyFactoryObject instance is set to false. This + means that each proxy object will be unique. Thus, you can configure + each proxy object with its' own individual advice(s) using the following + syntax // Will return un-advised instance of proxy object MyInterface myProxyObject1 = (MyInterface)ctx.GetObject("MyObject"); @@ -1594,28 +1589,28 @@ MyInterface myProxyObject2 = (MyInterface)ctx.GetObject("MyObject"); Proxying mechanisms Spring creates AOP proxies built at runtime through the use of the - TypeBuilder API. + TypeBuilder API. Two types of proxies can be created, composition based or inheritance based. If the target object implements at least one interface then a composition based proxy will be created, otherwise an inheritance - based proxy will be created. + based proxy will be created. The composition based proxy is implemented by creating a type that implements all the interfaces specified on the target object. The actual class name of this dynamic type is 'GUID' like. A private field holds the target object and the dynamic type implementation will first execute any advice before or after making the target object method call on the target - object. + object. The inheritance based mechanism creates a dynamic type where that inherits from the target type. This lets you downcast to the target type if needed. Please note that in both cases a target method implementation that calls other methods on the target object will not be advised. To force inheritance based proxies you should either set the - ProxyTargetType to true property of a ProxyFactory - or set the XML namespace element proxy-target-type = - true when using an AOP schema based configuration. + ProxyTargetType to true property of a ProxyFactory or + set the XML namespace element proxy-target-type = true + when using an AOP schema based configuration. An important alternative approach to inheritance based proxies is @@ -2200,6 +2195,28 @@ Saving speaker... + + PointcutFilteringAutoProxyCreator + + An AutoProxyCreator that identified objects to proxy by matching + a specified IPointcut. + + + + TypeNameAutoProxyCreator + + An AutoProxyCreator that identifies objects to proxy by matching + their Type.FullName against a list of + patterns. + + + + AbstractFilteringAutoProxyCreator + + The base class for AutoProxyCreator implementations that mark + objects eligible for proxying based on arbitrary criteria. + + AbstractAutoProxyCreator @@ -2448,11 +2465,11 @@ object oldTarget = swapper.swap(newTarget); </object> This advisor is obtained by calling a convenience method on the - AbstractPoolingTargetSource class, hence the use - of MethodInvokingFactoryObject. This advisor's - name ('poolConfigAdvisor' here) must be in the list - of interceptor names in the ProxyFactoryObject - exposing the pooled object. + AbstractPoolingTargetSource class, hence the use of + MethodInvokingFactoryObject. This advisor's name + ('poolConfigAdvisor' here) must be in the list of + interceptor names in the ProxyFactoryObject exposing + the pooled object. The cast will look as follows: @@ -2540,4 +2557,4 @@ Console.WriteLine("Max pool size is " + conf.getMaxSize()); AOP, take a look at the test suite as it illustrates advanced features not discussed in this document. - \ No newline at end of file +