|
Spring Framework example source code file (AbstractAspectJAdvice.java)
The Spring Framework AbstractAspectJAdvice.java source code
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.aop.aspectj;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.weaver.tools.JoinPointMatch;
import org.aspectj.weaver.tools.PointcutParameter;
import org.springframework.aop.AopInvocationException;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
import org.springframework.aop.support.ComposablePointcut;
import org.springframework.aop.support.MethodMatchers;
import org.springframework.aop.support.StaticMethodMatcher;
import org.springframework.core.JdkVersion;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.PrioritizedParameterNameDiscoverer;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
/**
* Base class for AOP Alliance {@link org.aopalliance.aop.Advice} classes
* wrapping an AspectJ aspect or an AspectJ-annotated advice method.
*
* @author Rod Johnson
* @author Adrian Colyer
* @author Juergen Hoeller
* @author Ramnivas Laddad
* @since 2.0
*/
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation {
/**
* Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint.
*/
protected static final String JOIN_POINT_KEY = JoinPoint.class.getName();
/**
* Lazily instantiate joinpoint for the current invocation.
* Requires MethodInvocation to be bound with ExposeInvocationInterceptor.
* <p>Do not use if access is available to the current ReflectiveMethodInvocation
* (in an around advice).
* @return current AspectJ joinpoint, or through an exception if we're not in a
* Spring AOP invocation.
*/
public static JoinPoint currentJoinPoint() {
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
JoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);
if (jp == null) {
jp = new MethodInvocationProceedingJoinPoint(pmi);
pmi.setUserAttribute(JOIN_POINT_KEY, jp);
}
return jp;
}
protected final Method aspectJAdviceMethod;
/** The total number of arguments we have to populate on advice dispatch */
private final int adviceInvocationArgumentCount;
private final AspectJExpressionPointcut pointcut;
private final AspectInstanceFactory aspectInstanceFactory;
/**
* The name of the aspect (ref bean) in which this advice was defined (used
* when determining advice precedence so that we can determine
* whether two pieces of advice come from the same aspect).
*/
private String aspectName;
/**
* The order of declaration of this advice within the aspect.
*/
private int declarationOrder;
/**
* This will be non-null if the creator of this advice object knows the argument names
* and sets them explicitly
*/
private String[] argumentNames = null;
/** Non-null if after throwing advice binds the thrown value */
private String throwingName = null;
/** Non-null if after returning advice binds the return value */
private String returningName = null;
private Class discoveredReturningType = Object.class;
private Class discoveredThrowingType = Object.class;
/**
* Index for thisJoinPoint argument (currently only
* supported at index 0 if present at all)
*/
private int joinPointArgumentIndex = -1;
/**
* Index for thisJoinPointStaticPart argument (currently only
* supported at index 0 if present at all)
*/
private int joinPointStaticPartArgumentIndex = -1;
private Map argumentBindings = null;
private boolean argumentsIntrospected = false;
// The actual type is java.lang.reflect.Type,
// but for JDK 1.4 compatibility we use Object as the static type.
private Object discoveredReturningGenericType;
// Note: Unlike return type, no such generic information is needed for the throwing type,
// since Java doesn't allow exception types to be parameterized.
/**
* Create a new AbstractAspectJAdvice for the given advice method.
* @param aspectJAdviceMethod the AspectJ-style advice method
* @param pointcut the AspectJ expression pointcut
* @param aspectInstanceFactory the factory for aspect instances
*/
public AbstractAspectJAdvice(
Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) {
Assert.notNull(aspectJAdviceMethod, "Advice method must not be null");
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.adviceInvocationArgumentCount = this.aspectJAdviceMethod.getParameterTypes().length;
this.pointcut = pointcut;
this.aspectInstanceFactory = aspectInstanceFactory;
}
/**
* Return the AspectJ-style advice method.
*/
public final Method getAspectJAdviceMethod() {
return this.aspectJAdviceMethod;
}
/**
* Return the AspectJ expression pointcut.
*/
public final AspectJExpressionPointcut getPointcut() {
calculateArgumentBindings();
return this.pointcut;
}
/**
* Build a 'safe' pointcut that excludes the AspectJ advice method itself.
* @return a composable pointcut that builds on the original AspectJ expression pointcut
* @see #getPointcut()
*/
public final Pointcut buildSafePointcut() {
Pointcut pc = getPointcut();
MethodMatcher safeMethodMatcher = MethodMatchers.intersection(
new AdviceExcludingMethodMatcher(this.aspectJAdviceMethod), pc.getMethodMatcher());
return new ComposablePointcut(pc.getClassFilter(), safeMethodMatcher);
}
/**
* Return the factory for aspect instances.
*/
public final AspectInstanceFactory getAspectInstanceFactory() {
return this.aspectInstanceFactory;
}
/**
* Return the ClassLoader for aspect instances.
*/
public final ClassLoader getAspectClassLoader() {
return this.aspectInstanceFactory.getAspectClassLoader();
}
public int getOrder() {
return this.aspectInstanceFactory.getOrder();
}
public void setAspectName(String name) {
this.aspectName = name;
}
public String getAspectName() {
return this.aspectName;
}
/**
* Sets the <b>declaration order of this advice within the aspect
*/
public void setDeclarationOrder(int order) {
this.declarationOrder = order;
}
public int getDeclarationOrder() {
return this.declarationOrder;
}
/**
* Set by creator of this advice object if the argument names are known.
* <p>This could be for example because they have been explicitly specified in XML,
* or in an advice annotation.
* @param argNames comma delimited list of arg names
*/
public void setArgumentNames(String argNames) {
String[] tokens = StringUtils.commaDelimitedListToStringArray(argNames);
setArgumentNamesFromStringArray(tokens);
}
public void setArgumentNamesFromStringArray(String[] args) {
this.argumentNames = new String[args.length];
for (int i = 0; i < args.length; i++) {
this.argumentNames[i] = StringUtils.trimWhitespace(args[i]);
if (!isVariableName(this.argumentNames[i])) {
throw new IllegalArgumentException(
"'argumentNames' property of AbstractAspectJAdvice contains an argument name '" +
this.argumentNames[i] + "' that is not a valid Java identifier");
}
}
if (argumentNames != null) {
if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) {
// May need to add implicit join point arg name...
Class firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
if (firstArgType == JoinPoint.class ||
firstArgType == ProceedingJoinPoint.class ||
firstArgType == JoinPoint.StaticPart.class) {
String[] oldNames = argumentNames;
argumentNames = new String[oldNames.length + 1];
argumentNames[0] = "THIS_JOIN_POINT";
System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length);
}
}
}
}
public void setReturningName(String name) {
throw new UnsupportedOperationException("Only afterReturning advice can be used to bind a return value");
}
/**
* We need to hold the returning name at this level for argument binding calculations,
* this method allows the afterReturning advice subclass to set the name.
*/
protected void setReturningNameNoCheck(String name) {
// name could be a variable or a type...
if (isVariableName(name)) {
this.returningName = name;
}
else {
// assume a type
try {
this.discoveredReturningType = ClassUtils.forName(name, getAspectClassLoader());
}
catch (Throwable ex) {
throw new IllegalArgumentException("Returning name '" + name +
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
"Root cause: " + ex);
}
}
}
protected Class getDiscoveredReturningType() {
return this.discoveredReturningType;
}
protected Object getDiscoveredReturningGenericType() {
return this.discoveredReturningGenericType;
}
public void setThrowingName(String name) {
throw new UnsupportedOperationException("Only afterThrowing advice can be used to bind a thrown exception");
}
/**
* We need to hold the throwing name at this level for argument binding calculations,
* this method allows the afterThrowing advice subclass to set the name.
*/
protected void setThrowingNameNoCheck(String name) {
// name could be a variable or a type...
if (isVariableName(name)) {
this.throwingName = name;
}
else {
// assume a type
try {
this.discoveredThrowingType = ClassUtils.forName(name, getAspectClassLoader());
}
catch (Throwable ex) {
throw new IllegalArgumentException("Throwing name '" + name +
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
"Root cause: " + ex);
}
}
}
protected Class getDiscoveredThrowingType() {
return this.discoveredThrowingType;
}
private boolean isVariableName(String name) {
char[] chars = name.toCharArray();
if (!Character.isJavaIdentifierStart(chars[0])) {
return false;
}
for (int i = 1; i < chars.length; i++) {
if (!Character.isJavaIdentifierPart(chars[i])) {
return false;
}
}
return true;
}
/**
* Do as much work as we can as part of the set-up so that argument binding
* on subsequent advice invocations can be as fast as possible.
* <p>If the first argument is of type JoinPoint or ProceedingJoinPoint then we
* pass a JoinPoint in that position (ProceedingJoinPoint for around advice).
* <p>If the first argument is of type
Other Spring Framework examples (source code examples)Here is a short list of links related to this Spring Framework AbstractAspectJAdvice.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.