KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > aop > aspectj > AbstractAspectJAdvice


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.aop.aspectj;
18
19 import java.lang.reflect.InvocationTargetException JavaDoc;
20 import java.lang.reflect.Method JavaDoc;
21 import java.lang.reflect.Modifier JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import org.aopalliance.aop.Advice;
26 import org.aopalliance.intercept.MethodInvocation;
27 import org.aspectj.lang.JoinPoint;
28 import org.aspectj.lang.ProceedingJoinPoint;
29 import org.aspectj.weaver.tools.JoinPointMatch;
30 import org.aspectj.weaver.tools.PointcutParameter;
31
32 import org.springframework.aop.AopInvocationException;
33 import org.springframework.aop.MethodMatcher;
34 import org.springframework.aop.Pointcut;
35 import org.springframework.aop.ProxyMethodInvocation;
36 import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
37 import org.springframework.aop.support.ComposablePointcut;
38 import org.springframework.aop.support.MethodMatchers;
39 import org.springframework.aop.support.StaticMethodMatcher;
40 import org.springframework.beans.factory.InitializingBean;
41 import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
42 import org.springframework.core.ParameterNameDiscoverer;
43 import org.springframework.core.PrioritizedParameterNameDiscoverer;
44 import org.springframework.util.Assert;
45 import org.springframework.util.ClassUtils;
46 import org.springframework.util.StringUtils;
47
48 /**
49  * Superclass for Spring Advices wrapping an AspectJ aspect
50  * or annotated advice method.
51  *
52  * @author Rod Johnson
53  * @author Adrian Colyer
54  * @author Juergen Hoeller
55  * @since 2.0
56  */

57 public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, InitializingBean {
58     
59     /**
60      * Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint.
61      */

62     protected final static String JavaDoc JOIN_POINT_KEY = JoinPoint.class.getName();
63
64
65     /**
66      * Lazily instantiate joinpoint for the current invocation.
67      * Requires MethodInvocation to be bound with ExposeInvocationInterceptor.
68      * <p>Do not use if access is available to the current ReflectiveMethodInvocation
69      * (in an around advice).
70      * @return current AspectJ joinpoint, or through an exception if we're not in a
71      * Spring AOP invocation.
72      */

73     public static JoinPoint currentJoinPoint() {
74         MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
75         if (!(mi instanceof ProxyMethodInvocation)) {
76             throw new IllegalStateException JavaDoc("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
77         }
78         ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
79         JoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);
80         if (jp == null) {
81             jp = new MethodInvocationProceedingJoinPoint(pmi);
82             pmi.setUserAttribute(JOIN_POINT_KEY, jp);
83         }
84         return jp;
85     }
86
87
88     protected final Method JavaDoc aspectJAdviceMethod;
89
90     /** The total number of arguments we have to populate on advice dispatch */
91     private final int adviceInvocationArgumentCount;
92
93     private final AspectJExpressionPointcut pointcut;
94
95     private final AspectInstanceFactory aspectInstanceFactory;
96
97     /**
98      * The name of the aspect (ref bean) in which this advice was defined (used
99      * when determining advice precedence so that we can determine
100      * whether two pieces of advice come from the same aspect).
101      */

102     private String JavaDoc aspectName;
103
104     /**
105      * The order of declaration of this advice within the aspect.
106      */

107     private int declarationOrder;
108
109     /**
110      * This will be non-null if the creator of this advice object knows the argument names
111      * and sets them explicitly
112      */

113     private String JavaDoc[] argumentNames = null;
114
115     /** Non-null if after throwing advice binds the thrown value */
116     private String JavaDoc throwingName = null;
117
118     /** Non-null if after returning advice binds the return value */
119     private String JavaDoc returningName = null;
120
121     private Class JavaDoc discoveredReturningType = Object JavaDoc.class;
122
123     private Class JavaDoc discoveredThrowingType = Object JavaDoc.class;
124
125     /**
126      * Index for thisJoinPoint argument (currently only
127      * supported at index 0 if present at all)
128      */

129     private int joinPointArgumentIndex = -1;
130
131     /**
132      * Index for thisJoinPointStaticPart argument (currently only
133      * supported at index 0 if present at all)
134      */

135     private int joinPointStaticPartArgumentIndex = -1;
136
137     private final Map JavaDoc argumentBindings = new HashMap JavaDoc();
138
139
140     /**
141      * Create a new AbstractAspectJAdvice for the given advice method.
142      * @param aspectJAdviceMethod the AspectJ-style advice method
143      * @param pointcut the AspectJ expression pointcut
144      * @param aspectInstanceFactory the factory for aspect instances
145      */

146     public AbstractAspectJAdvice(
147             Method JavaDoc aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) {
148
149         Assert.notNull(aspectJAdviceMethod, "Advice method must not be null");
150         this.aspectJAdviceMethod = aspectJAdviceMethod;
151         this.adviceInvocationArgumentCount = this.aspectJAdviceMethod.getParameterTypes().length;
152         this.pointcut = pointcut;
153         this.aspectInstanceFactory = aspectInstanceFactory;
154     }
155
156
157     /**
158      * Return the AspectJ-style advice method.
159      */

160     public final Method JavaDoc getAspectJAdviceMethod() {
161         return this.aspectJAdviceMethod;
162     }
163
164     /**
165      * Return the AspectJ expression pointcut.
166      */

167     public final AspectJExpressionPointcut getPointcut() {
168         return this.pointcut;
169     }
170
171     /**
172      * Build a 'safe' pointcut that excludes the AspectJ advice method itself.
173      * @return a composable pointcut that builds on the original AspectJ expression pointcut
174      * @see #getPointcut()
175      */

176     public final Pointcut buildSafePointcut() {
177         MethodMatcher safeMethodMatcher = MethodMatchers.intersection(
178                 new AdviceExcludingMethodMatcher(this.aspectJAdviceMethod), this.pointcut.getMethodMatcher());
179         return new ComposablePointcut(this.pointcut.getClassFilter(), safeMethodMatcher);
180     }
181
182     /**
183      * Return the factory for aspect instances.
184      */

185     public final AspectInstanceFactory getAspectInstanceFactory() {
186         return this.aspectInstanceFactory;
187     }
188
189     public int getOrder() {
190         return this.aspectInstanceFactory.getOrder();
191     }
192
193
194     public void setAspectName(String JavaDoc name) {
195         this.aspectName = name;
196     }
197     
198     public String JavaDoc getAspectName() {
199         return this.aspectName;
200     }
201
202     /**
203      * Sets the <b>declaration order</b> of this advice within the aspect
204      */

205     public void setDeclarationOrder(int order) {
206         this.declarationOrder = order;
207     }
208
209     public int getDeclarationOrder() {
210         return this.declarationOrder;
211     }
212
213     /**
214      * Set by creator of this advice object if the argument names are known.
215      * <p>This could be for example because they have been explicitly specified in XML,
216      * or in an advice annotation.
217      * @param argNames comma delimited list of arg names
218      */

219     public void setArgumentNames(String JavaDoc argNames) {
220         String JavaDoc[] tokens = StringUtils.commaDelimitedListToStringArray(argNames);
221         setArgumentNamesFromStringArray(tokens);
222     }
223
224     public void setArgumentNamesFromStringArray(String JavaDoc[] args) {
225         this.argumentNames = new String JavaDoc[args.length];
226         for (int i = 0; i < args.length; i++) {
227             this.argumentNames[i] = StringUtils.trimWhitespace(args[i]);
228             if (!isVariableName(this.argumentNames[i])) {
229                 throw new IllegalArgumentException JavaDoc(
230                         "'argumentNames' property of AbstractAspectJAdvice contains an argument name '" +
231                         this.argumentNames[i] + "' that is not a valid Java identifier");
232             }
233         }
234     }
235
236     public void setReturningName(String JavaDoc name) {
237         throw new UnsupportedOperationException JavaDoc("Only afterReturning advice can be used to bind a return value");
238     }
239
240     /**
241      * We need to hold the returning name at this level for argument binding calculations,
242      * this method allows the afterReturning advice subclass to set the name.
243      */

244     protected void setReturningNameNoCheck(String JavaDoc name) {
245         // name could be a variable or a type...
246
if (isVariableName(name)) {
247             this.returningName = name;
248         }
249         else {
250             // assume a type
251
try {
252                 this.discoveredReturningType = ClassUtils.forName(name);
253             }
254             catch (Throwable JavaDoc ex) {
255                 throw new IllegalArgumentException JavaDoc("Returning name '" + name +
256                         "' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
257                         "Root cause: " + ex);
258             }
259         }
260     }
261
262     protected Class JavaDoc getDiscoveredReturningType() {
263         return this.discoveredReturningType;
264     }
265
266     public void setThrowingName(String JavaDoc name) {
267         throw new UnsupportedOperationException JavaDoc("Only afterThrowing advice can be used to bind a thrown exception");
268     }
269
270     /**
271      * We need to hold the throwing name at this level for argument binding calculations,
272      * this method allows the afterThrowing advice subclass to set the name.
273      */

274     protected void setThrowingNameNoCheck(String JavaDoc name) {
275         // name could be a variable or a type...
276
if (isVariableName(name)) {
277             this.throwingName = name;
278         }
279         else {
280             // assume a type
281
try {
282                 this.discoveredThrowingType = ClassUtils.forName(name);
283             }
284             catch (Throwable JavaDoc ex) {
285                 throw new IllegalArgumentException JavaDoc("Throwing name '" + name +
286                         "' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
287                         "Root cause: " + ex);
288             }
289         }
290     }
291
292     protected Class JavaDoc getDiscoveredThrowingType() {
293         return this.discoveredThrowingType;
294     }
295
296     private boolean isVariableName(String JavaDoc name) {
297         char[] chars = name.toCharArray();
298         if (!Character.isJavaIdentifierStart(chars[0])) {
299             return false;
300         }
301         for (int i = 1; i < chars.length; i++) {
302             if (!Character.isJavaIdentifierPart(chars[i])) {
303                 return false;
304             }
305         }
306         return true;
307     }
308
309
310     /**
311      * Argument names have to be discovered and set on the associated pointcut expression,
312      * and we also calculate argument bindings for advice invocation so that actual dispatch
313      * can be as fast as possible.
314      */

315     public void afterPropertiesSet() throws Exception JavaDoc {
316         calculateArgumentBindings();
317     }
318
319     /**
320      * Do as much work as we can as part of the set-up so that argument binding
321      * on subsequent advice invocations can be as fast as possible.
322      * <p>If the first argument is of type JoinPoint or ProceedingJoinPoint then we
323      * pass a JoinPoint in that position (ProceedingJoinPoint for around advice).
324      * <p>If the first argument is of type <code>JoinPoint.StaticPart</code>
325      * then we pass a <code>JoinPoint.StaticPart</code> in that position.
326      * <p>Remaining arguments have to be bound by pointcut evaluation at
327      * a given join point. We will get back a map from argument name to
328      * value. We need to calculate which advice parameter needs to be bound
329      * to which argument name. There are multiple strategies for determining
330      * this binding, which are arranged in a ChainOfResponsibility.
331      */

332     private void calculateArgumentBindings() {
333         // The simple case... nothing to bind.
334
if (this.adviceInvocationArgumentCount == 0) {
335             return;
336         }
337
338         int numUnboundArgs = this.adviceInvocationArgumentCount;
339
340         Class JavaDoc[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
341         if (maybeBindJoinPoint(parameterTypes[0])) {
342             numUnboundArgs--;
343         }
344         else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
345             numUnboundArgs--;
346         }
347             
348         if (numUnboundArgs > 0) {
349             // need to bind arguments by name as returned from the pointcut match
350
bindArgumentsByName(numUnboundArgs);
351         }
352     }
353
354     private boolean maybeBindJoinPoint(Class JavaDoc candidateParameterType) {
355         if ((candidateParameterType.equals(JoinPoint.class)) ||
356             (candidateParameterType.equals(ProceedingJoinPoint.class))) {
357             this.joinPointArgumentIndex = 0;
358             return true;
359         }
360         else {
361             return false;
362         }
363     }
364
365     private boolean maybeBindJoinPointStaticPart(Class JavaDoc candidateParameterType) {
366         if (candidateParameterType.equals(JoinPoint.StaticPart.class)) {
367             this.joinPointStaticPartArgumentIndex = 0;
368             return true;
369         }
370         else {
371             return false;
372         }
373     }
374
375     private void bindArgumentsByName(int numArgumentsExpectingToBind) {
376         if (this.argumentNames == null) {
377             this.argumentNames = createParameterNameDiscoverer().getParameterNames(this.aspectJAdviceMethod);
378         }
379         if (this.argumentNames != null) {
380             // We have been able to determine the arg names.
381
bindExplicitArguments(numArgumentsExpectingToBind);
382         }
383         else {
384             throw new IllegalStateException JavaDoc("Advice method [" + this.aspectJAdviceMethod.getName() + "] " +
385                     "requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " +
386                     "the argument names were not specified and could not be discovered.");
387         }
388     }
389
390     /**
391      * Create a ParameterNameDiscoverer to be used for argument binding.
392      * <p>The default implementation creates a {@link PrioritizedParameterNameDiscoverer}
393      * containing a {@link LocalVariableTableParameterNameDiscoverer} and an
394      * {@link AspectJAdviceParameterNameDiscoverer}.
395      */

396     protected ParameterNameDiscoverer createParameterNameDiscoverer() {
397         // We need to discover them, or if that fails, guess,
398
// and if we can't guess with 100% accuracy, fail.
399
PrioritizedParameterNameDiscoverer discoverer = new PrioritizedParameterNameDiscoverer();
400         discoverer.addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
401         AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer =
402                 new AspectJAdviceParameterNameDiscoverer(this.pointcut.getExpression());
403         adviceParameterNameDiscoverer.setReturningName(this.returningName);
404         adviceParameterNameDiscoverer.setThrowingName(this.throwingName);
405         // Last in chain, so if we're called and we fail, that's bad...
406
adviceParameterNameDiscoverer.setRaiseExceptions(true);
407         discoverer.addDiscoverer(adviceParameterNameDiscoverer);
408         return discoverer;
409     }
410
411     private void bindExplicitArguments(int numArgumentsLeftToBind) {
412         int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
413         if (this.argumentNames.length != numExpectedArgumentNames) {
414             throw new IllegalStateException JavaDoc("Expecting to find " + numExpectedArgumentNames
415                     + " arguments to bind by name in advice, but actually found " +
416                     this.argumentNames.length + " arguments.");
417         }
418
419         // So we match in number...
420
int argumentIndexOffset = this.adviceInvocationArgumentCount - numArgumentsLeftToBind;
421         for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
422             this.argumentBindings.put(this.argumentNames[i],new Integer JavaDoc(i));
423         }
424
425         // Check that returning and throwing were in the argument names list if
426
// specified, and find the discovered argument types.
427
if (this.returningName != null) {
428             if (!this.argumentBindings.containsKey(this.returningName)) {
429                 throw new IllegalStateException JavaDoc("Returning argument name '"
430                         + this.returningName + "' was not bound in advice arguments");
431             }
432             else {
433                 Integer JavaDoc index = (Integer JavaDoc) this.argumentBindings.get(this.returningName);
434                 this.discoveredReturningType = this.aspectJAdviceMethod.getParameterTypes()[index.intValue()];
435             }
436         }
437         if (this.throwingName != null) {
438             if (!this.argumentBindings.containsKey(this.throwingName)) {
439                 throw new IllegalStateException JavaDoc("Throwing argument name '"
440                         + this.throwingName + "' was not bound in advice arguments");
441             }
442             else {
443                 Integer JavaDoc index = (Integer JavaDoc) this.argumentBindings.get(this.throwingName);
444                 this.discoveredThrowingType = this.aspectJAdviceMethod.getParameterTypes()[index.intValue()];
445             }
446         }
447
448         // configure the pointcut expression accordingly.
449
configurePointcutParameters(argumentIndexOffset);
450     }
451
452     /**
453      * All parameters from argumentIndexOffset onwards are candidates for
454      * pointcut parameters - but returning and throwing vars are handled differently
455      * and must be removed from the list if present.
456      */

457     private void configurePointcutParameters(int argumentIndexOffset) {
458         int numParametersToRemove = argumentIndexOffset;
459         if (returningName != null) {
460             numParametersToRemove++;
461         }
462         if (throwingName != null) {
463             numParametersToRemove++;
464         }
465         String JavaDoc[] pointcutParameterNames = new String JavaDoc[this.argumentNames.length - numParametersToRemove];
466         Class JavaDoc[] pointcutParameterTypes = new Class JavaDoc[pointcutParameterNames.length];
467         Class JavaDoc[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();
468
469         int index = 0;
470         for (int i = 0; i < this.argumentNames.length; i++) {
471             if (i < argumentIndexOffset) {
472                 continue;
473             }
474             if (this.argumentNames[i].equals(this.returningName) ||
475                 this.argumentNames[i].equals(this.throwingName)) {
476                 continue;
477             }
478             pointcutParameterNames[index] = this.argumentNames[i];
479             pointcutParameterTypes[index] = methodParameterTypes[i];
480             index++;
481         }
482         
483         this.pointcut.setParameterNames(pointcutParameterNames);
484         this.pointcut.setParameterTypes(pointcutParameterTypes);
485     }
486
487     /**
488      * Take the arguments at the method execution join point and output a set of arguments
489      * to the advice method
490      * @param jpMatch the join point match that matched this execution join point
491      * @param returnValue the return value from the method execution (may be null)
492      * @param t the exception thrown by the method execution (may be null)
493      * @return the empty array if there are no arguments
494      */

495     protected Object JavaDoc[] argBinding(JoinPoint jp, JoinPointMatch jpMatch, Object JavaDoc returnValue, Throwable JavaDoc t) {
496         // AMC start
497
Object JavaDoc[] adviceInvocationArgs = new Object JavaDoc[this.adviceInvocationArgumentCount];
498         int numBound = 0;
499
500         if (this.joinPointArgumentIndex != -1) {
501             adviceInvocationArgs[this.joinPointArgumentIndex] = jp;
502             numBound++;
503         }
504         else if (this.joinPointStaticPartArgumentIndex != -1) {
505             adviceInvocationArgs[this.joinPointStaticPartArgumentIndex] = jp.getStaticPart();
506             numBound++;
507         }
508
509         if (!this.argumentBindings.isEmpty()) {
510             // binding from pointcut match
511
if (jpMatch != null) {
512                 PointcutParameter[] parameterBindings = jpMatch.getParameterBindings();
513                 for (int i = 0; i < parameterBindings.length; i++) {
514                     PointcutParameter parameter = parameterBindings[i];
515                     String JavaDoc name = parameter.getName();
516                     Integer JavaDoc index = (Integer JavaDoc) this.argumentBindings.get(name);
517                     adviceInvocationArgs[index.intValue()] = parameter.getBinding();
518                     numBound++;
519                 }
520             }
521             // binding from returning clause
522
if (this.returningName != null) {
523                 Integer JavaDoc index = (Integer JavaDoc) this.argumentBindings.get(this.returningName);
524                 adviceInvocationArgs[index.intValue()] = returnValue;
525                 numBound++;
526             }
527             // binding from thrown exception
528
if (this.throwingName != null) {
529                 Integer JavaDoc index = (Integer JavaDoc) this.argumentBindings.get(this.throwingName);
530                 adviceInvocationArgs[index.intValue()] = t;
531                 numBound++;
532             }
533         }
534
535         if (numBound != this.adviceInvocationArgumentCount) {
536             throw new IllegalStateException JavaDoc("Required to bind " + this.adviceInvocationArgumentCount
537                     + " arguments, but only bound " + numBound + " (JoinPointMatch " +
538                     (jpMatch == null ? "was NOT" : "WAS") +
539                     " bound in invocation)");
540         }
541
542         return adviceInvocationArgs;
543     }
544
545
546     /**
547      * Invoke the advice method.
548      * @param jpMatch the JoinPointMatch that matched this execution join point
549      * @param returnValue the return value from the method execution (may be null)
550      * @param ex the exception thrown by the method execution (may be null)
551      * @return the invocation result
552      * @throws Throwable in case of invocation failure
553      */

554     protected Object JavaDoc invokeAdviceMethod(JoinPointMatch jpMatch, Object JavaDoc returnValue, Throwable JavaDoc ex) throws Throwable JavaDoc {
555         return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
556     }
557
558     // As above, but in this case we are given the join point.
559
protected Object JavaDoc invokeAdviceMethod(JoinPoint jp, JoinPointMatch jpMatch, Object JavaDoc returnValue, Throwable JavaDoc t)
560             throws Throwable JavaDoc {
561
562         return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
563     }
564
565     protected Object JavaDoc invokeAdviceMethodWithGivenArgs(Object JavaDoc[] args) throws Throwable JavaDoc {
566         Object JavaDoc[] actualArgs = args;
567         if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
568             actualArgs = null;
569         }
570         try {
571             if (!Modifier.isPublic(this.aspectJAdviceMethod.getModifiers()) ||
572                     !Modifier.isPublic(this.aspectJAdviceMethod.getDeclaringClass().getModifiers())) {
573                 this.aspectJAdviceMethod.setAccessible(true);
574             }
575             // TODO AopUtils.invokeJoinpointUsingReflection
576
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
577         }
578         catch (IllegalArgumentException JavaDoc ex) {
579             throw new AopInvocationException("Mismatch on arguments to advice method [" +
580                     this.aspectJAdviceMethod + "]; pointcut expression [" +
581                     this.pointcut.getPointcutExpression() + "]", ex);
582         }
583         catch (InvocationTargetException JavaDoc ex) {
584             throw ex.getTargetException();
585         }
586     }
587
588     /**
589      * Overridden in around advice to return proceeding join point.
590      */

591     protected JoinPoint getJoinPoint() {
592         return currentJoinPoint();
593     }
594
595     /**
596      * Get the current join point match at the join point we are being dispatched on.
597      */

598     protected JoinPointMatch getJoinPointMatch() {
599         MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
600         if (!(mi instanceof ProxyMethodInvocation)) {
601             throw new IllegalStateException JavaDoc("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
602         }
603         return getJoinPointMatch((ProxyMethodInvocation) mi);
604     }
605
606     // Note: We can't use JoinPointMatch.getClass().getName() as the key, since
607
// Spring AOP does all the matching at a join point, and then all the invocations.
608
// Under this scenario, if we just use JoinPointMatch as the key, then
609
// 'last man wins' which is not what we want at all.
610
// Using the expression is guaranteed to be safe, since 2 identical expressions
611
// are guaranteed to bind in exactly the same way.
612
protected JoinPointMatch getJoinPointMatch(ProxyMethodInvocation rmi) {
613         return (JoinPointMatch) rmi.getUserAttribute(this.pointcut.getExpression());
614     }
615
616
617     public String JavaDoc toString() {
618         return getClass().getName() + ": advice method [" + this.aspectJAdviceMethod + "]; " +
619                 "aspect name '" + this.aspectName + "'";
620     }
621
622
623     /**
624      * MethodMatcher that excludes the specified advice method.
625      * @see AbstractAspectJAdvice#buildSafePointcut()
626      */

627     private static class AdviceExcludingMethodMatcher extends StaticMethodMatcher {
628
629         private final Method JavaDoc adviceMethod;
630
631         public AdviceExcludingMethodMatcher(Method JavaDoc adviceMethod) {
632             this.adviceMethod = adviceMethod;
633         }
634
635         public boolean matches(Method JavaDoc method, Class JavaDoc targetClass) {
636             return !this.adviceMethod.equals(method);
637         }
638     }
639
640 }
641
Popular Tags