|
|
|
@ -16,6 +16,9 @@ |
|
|
|
|
|
|
|
|
|
|
|
package org.springframework.aop.aspectj; |
|
|
|
package org.springframework.aop.aspectj; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
|
|
|
import java.io.ObjectInputStream; |
|
|
|
|
|
|
|
import java.io.Serializable; |
|
|
|
import java.lang.reflect.InvocationTargetException; |
|
|
|
import java.lang.reflect.InvocationTargetException; |
|
|
|
import java.lang.reflect.Method; |
|
|
|
import java.lang.reflect.Method; |
|
|
|
import java.lang.reflect.Type; |
|
|
|
import java.lang.reflect.Type; |
|
|
|
@ -55,7 +58,8 @@ import org.springframework.util.StringUtils; |
|
|
|
* @author Ramnivas Laddad |
|
|
|
* @author Ramnivas Laddad |
|
|
|
* @since 2.0 |
|
|
|
* @since 2.0 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation { |
|
|
|
@SuppressWarnings("serial") |
|
|
|
|
|
|
|
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint. |
|
|
|
* Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint. |
|
|
|
@ -86,10 +90,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected final Method aspectJAdviceMethod; |
|
|
|
private final Class<?> declaringClass; |
|
|
|
|
|
|
|
|
|
|
|
/** The total number of arguments we have to populate on advice dispatch */ |
|
|
|
private final String methodName; |
|
|
|
private final int adviceInvocationArgumentCount; |
|
|
|
|
|
|
|
|
|
|
|
private final Class<?>[] parameterTypes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected transient Method aspectJAdviceMethod; |
|
|
|
|
|
|
|
|
|
|
|
private final AspectJExpressionPointcut pointcut; |
|
|
|
private final AspectJExpressionPointcut pointcut; |
|
|
|
|
|
|
|
|
|
|
|
@ -135,7 +142,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private int joinPointStaticPartArgumentIndex = -1; |
|
|
|
private int joinPointStaticPartArgumentIndex = -1; |
|
|
|
|
|
|
|
|
|
|
|
private Map<String, Integer> argumentBindings = null; |
|
|
|
private Map<String, Integer> argumentBindings; |
|
|
|
|
|
|
|
|
|
|
|
private boolean argumentsIntrospected = false; |
|
|
|
private boolean argumentsIntrospected = false; |
|
|
|
|
|
|
|
|
|
|
|
@ -154,8 +161,10 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) { |
|
|
|
Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) { |
|
|
|
|
|
|
|
|
|
|
|
Assert.notNull(aspectJAdviceMethod, "Advice method must not be null"); |
|
|
|
Assert.notNull(aspectJAdviceMethod, "Advice method must not be null"); |
|
|
|
|
|
|
|
this.declaringClass = aspectJAdviceMethod.getDeclaringClass(); |
|
|
|
|
|
|
|
this.methodName = aspectJAdviceMethod.getName(); |
|
|
|
|
|
|
|
this.parameterTypes = aspectJAdviceMethod.getParameterTypes(); |
|
|
|
this.aspectJAdviceMethod = aspectJAdviceMethod; |
|
|
|
this.aspectJAdviceMethod = aspectJAdviceMethod; |
|
|
|
this.adviceInvocationArgumentCount = this.aspectJAdviceMethod.getParameterTypes().length; |
|
|
|
|
|
|
|
this.pointcut = pointcut; |
|
|
|
this.pointcut = pointcut; |
|
|
|
this.aspectInstanceFactory = aspectInstanceFactory; |
|
|
|
this.aspectInstanceFactory = aspectInstanceFactory; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -250,17 +259,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
this.argumentNames[i] + "' that is not a valid Java identifier"); |
|
|
|
this.argumentNames[i] + "' that is not a valid Java identifier"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (argumentNames != null) { |
|
|
|
if (this.argumentNames != null) { |
|
|
|
if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) { |
|
|
|
if (this.aspectJAdviceMethod.getParameterTypes().length == this.argumentNames.length + 1) { |
|
|
|
// May need to add implicit join point arg name...
|
|
|
|
// May need to add implicit join point arg name...
|
|
|
|
Class<?> firstArgType = aspectJAdviceMethod.getParameterTypes()[0]; |
|
|
|
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0]; |
|
|
|
if (firstArgType == JoinPoint.class || |
|
|
|
if (firstArgType == JoinPoint.class || |
|
|
|
firstArgType == ProceedingJoinPoint.class || |
|
|
|
firstArgType == ProceedingJoinPoint.class || |
|
|
|
firstArgType == JoinPoint.StaticPart.class) { |
|
|
|
firstArgType == JoinPoint.StaticPart.class) { |
|
|
|
String[] oldNames = argumentNames; |
|
|
|
String[] oldNames = this.argumentNames; |
|
|
|
argumentNames = new String[oldNames.length + 1]; |
|
|
|
this.argumentNames = new String[oldNames.length + 1]; |
|
|
|
argumentNames[0] = "THIS_JOIN_POINT"; |
|
|
|
this.argumentNames[0] = "THIS_JOIN_POINT"; |
|
|
|
System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length); |
|
|
|
System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -359,11 +368,11 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public synchronized final void calculateArgumentBindings() { |
|
|
|
public synchronized final void calculateArgumentBindings() { |
|
|
|
// The simple case... nothing to bind.
|
|
|
|
// The simple case... nothing to bind.
|
|
|
|
if (this.argumentsIntrospected || this.adviceInvocationArgumentCount == 0) { |
|
|
|
if (this.argumentsIntrospected || this.parameterTypes.length == 0) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int numUnboundArgs = this.adviceInvocationArgumentCount; |
|
|
|
int numUnboundArgs = this.parameterTypes.length; |
|
|
|
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes(); |
|
|
|
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes(); |
|
|
|
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) { |
|
|
|
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) { |
|
|
|
numUnboundArgs--; |
|
|
|
numUnboundArgs--; |
|
|
|
@ -456,13 +465,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
|
|
|
|
|
|
|
|
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length; |
|
|
|
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length; |
|
|
|
if (this.argumentNames.length != numExpectedArgumentNames) { |
|
|
|
if (this.argumentNames.length != numExpectedArgumentNames) { |
|
|
|
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames |
|
|
|
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames + |
|
|
|
+ " arguments to bind by name in advice, but actually found " + |
|
|
|
" arguments to bind by name in advice, but actually found " + |
|
|
|
this.argumentNames.length + " arguments."); |
|
|
|
this.argumentNames.length + " arguments."); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// So we match in number...
|
|
|
|
// So we match in number...
|
|
|
|
int argumentIndexOffset = this.adviceInvocationArgumentCount - numArgumentsLeftToBind; |
|
|
|
int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind; |
|
|
|
for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) { |
|
|
|
for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) { |
|
|
|
this.argumentBindings.put(this.argumentNames[i], i); |
|
|
|
this.argumentBindings.put(this.argumentNames[i], i); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -471,8 +480,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
// specified, and find the discovered argument types.
|
|
|
|
// specified, and find the discovered argument types.
|
|
|
|
if (this.returningName != null) { |
|
|
|
if (this.returningName != null) { |
|
|
|
if (!this.argumentBindings.containsKey(this.returningName)) { |
|
|
|
if (!this.argumentBindings.containsKey(this.returningName)) { |
|
|
|
throw new IllegalStateException("Returning argument name '" |
|
|
|
throw new IllegalStateException("Returning argument name '" + this.returningName + |
|
|
|
+ this.returningName + "' was not bound in advice arguments"); |
|
|
|
"' was not bound in advice arguments"); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
Integer index = this.argumentBindings.get(this.returningName); |
|
|
|
Integer index = this.argumentBindings.get(this.returningName); |
|
|
|
@ -482,8 +491,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
} |
|
|
|
} |
|
|
|
if (this.throwingName != null) { |
|
|
|
if (this.throwingName != null) { |
|
|
|
if (!this.argumentBindings.containsKey(this.throwingName)) { |
|
|
|
if (!this.argumentBindings.containsKey(this.throwingName)) { |
|
|
|
throw new IllegalStateException("Throwing argument name '" |
|
|
|
throw new IllegalStateException("Throwing argument name '" + this.throwingName + |
|
|
|
+ this.throwingName + "' was not bound in advice arguments"); |
|
|
|
"' was not bound in advice arguments"); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
Integer index = this.argumentBindings.get(this.throwingName); |
|
|
|
Integer index = this.argumentBindings.get(this.throwingName); |
|
|
|
@ -543,7 +552,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
calculateArgumentBindings(); |
|
|
|
calculateArgumentBindings(); |
|
|
|
|
|
|
|
|
|
|
|
// AMC start
|
|
|
|
// AMC start
|
|
|
|
Object[] adviceInvocationArgs = new Object[this.adviceInvocationArgumentCount]; |
|
|
|
Object[] adviceInvocationArgs = new Object[this.parameterTypes.length]; |
|
|
|
int numBound = 0; |
|
|
|
int numBound = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (this.joinPointArgumentIndex != -1) { |
|
|
|
if (this.joinPointArgumentIndex != -1) { |
|
|
|
@ -580,11 +589,10 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (numBound != this.adviceInvocationArgumentCount) { |
|
|
|
if (numBound != this.parameterTypes.length) { |
|
|
|
throw new IllegalStateException("Required to bind " + this.adviceInvocationArgumentCount |
|
|
|
throw new IllegalStateException("Required to bind " + this.parameterTypes.length + |
|
|
|
+ " arguments, but only bound " + numBound + " (JoinPointMatch " + |
|
|
|
" arguments, but only bound " + numBound + " (JoinPointMatch " + |
|
|
|
(jpMatch == null ? "was NOT" : "WAS") + |
|
|
|
(jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)"); |
|
|
|
" bound in invocation)"); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return adviceInvocationArgs; |
|
|
|
return adviceInvocationArgs; |
|
|
|
@ -665,6 +673,16 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence |
|
|
|
"aspect name '" + this.aspectName + "'"; |
|
|
|
"aspect name '" + this.aspectName + "'"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { |
|
|
|
|
|
|
|
inputStream.defaultReadObject(); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (NoSuchMethodException ex) { |
|
|
|
|
|
|
|
throw new IllegalStateException("Failed to find advice method on deserialization", ex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* MethodMatcher that excludes the specified advice method. |
|
|
|
* MethodMatcher that excludes the specified advice method. |
|
|
|
|