⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractaspectjadvice.java

📁 struts+spring 源码 希望能给大家带来帮助
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
	 * and we also calculate argument bindings for advice invocation so that actual dispatch
	 * can be as fast as possible.
	 */
	public void afterPropertiesSet() throws Exception {
		calculateArgumentBindings();
	}	
	
	/**
	 * 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 <code>JoinPoint.StaticPart</code>
	 * then we pass a <code>JoinPoint.StaticPart</code> in that position.
	 * <p>Remaining arguments have to be bound by pointcut evaluation at
	 * a given join point. We will get back a map from argument name to
	 * value. We need to calculate which advice parameter needs to be bound
	 * to which argument name. There are multiple strategies for determining
	 * this binding, which are arranged in a ChainOfResponsibility.
	 */
	private void calculateArgumentBindings() {
		// The simple case... nothing to bind.
		if (this.numAdviceInvocationArguments == 0) {
			return;
		}
		
		int numUnboundArgs = this.numAdviceInvocationArguments;
		
		Class[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
		if (maybeBindJoinPoint(parameterTypes[0])) {
			numUnboundArgs--;
		} 
		else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
			numUnboundArgs--;
		}
			
		if (numUnboundArgs > 0) {
			// need to bind arguments by name as returned from the pointcut match
			bindArgumentsByName(numUnboundArgs);
		}
	}
	
	private boolean maybeBindJoinPoint(Class candidateParameterType) {
		if ((candidateParameterType.equals(JoinPoint.class)) ||
			(candidateParameterType.equals(ProceedingJoinPoint.class))) {
			this.joinPointArgumentIndex = 0;
			return true;
		}
		else {
			return false;
		}
	}
	
	private boolean maybeBindJoinPointStaticPart(Class candidateParameterType) {
		if (candidateParameterType.equals(JoinPoint.StaticPart.class)) {
			this.joinPointStaticPartArgumentIndex = 0;
			return true;
		} 
		else {
			return false;
		}
	}
	
	private void bindArgumentsByName(int numArgumentsExpectingToBind) {
		if (this.argumentNames == null) {
			// We need to discover them, or if that fails, guess,
			// and if we can't guess with 100% accuracy, fail.
			PrioritizedParameterNameDiscoverer discoverer = new PrioritizedParameterNameDiscoverer();
			discoverer.addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
			AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer = 
				new AspectJAdviceParameterNameDiscoverer(this.pointcutExpression.getExpression());
			adviceParameterNameDiscoverer.setReturningName(this.returningName);
			adviceParameterNameDiscoverer.setThrowingName(this.throwingName);
			// last in chain, so if we're called and we fail, that's bad...
			adviceParameterNameDiscoverer.setRaiseExceptions(true);
			discoverer.addDiscoverer(adviceParameterNameDiscoverer);
			
			this.argumentNames = discoverer.getParameterNames(this.aspectJAdviceMethod);
		}
		
		if (this.argumentNames != null) {
			// We have been able to determine the arg names.
			bindExplicitArguments(numArgumentsExpectingToBind);
		} 
		else {
			throw new IllegalStateException("Advice method [" + this.aspectJAdviceMethod.getName() + "] " +
					"requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " +
					"the argument names were not specified and could not be discovered.");
		}
	}

	private void bindExplicitArguments(int numArgumentsLeftToBind) {
		int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
		if (this.argumentNames.length != numExpectedArgumentNames) {
			throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames
					+ " arguments to bind by name in advice, but actually found " +
					this.argumentNames.length + " arguments.");
		}
		
		// so we match in number...
		int argumentIndexOffset = this.numAdviceInvocationArguments - numArgumentsLeftToBind;
		for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
			this.argumentBindings.put(this.argumentNames[i],new Integer(i));
		}
		
		// check that returning and throwing were in the argument names list if
		// specified, and find the discovered argument types
		if (this.returningName != null) {
			if (!this.argumentBindings.containsKey(this.returningName)) {
				throw new IllegalStateException("Returning argument name '" 
						+ this.returningName + "' was not bound in advice arguments");
			} 
			else {
				Integer index = (Integer) this.argumentBindings.get(this.returningName);
				this.discoveredReturningType = this.aspectJAdviceMethod.getParameterTypes()[index.intValue()];
			}
		}
		if (this.throwingName != null) {
			if (!this.argumentBindings.containsKey(this.throwingName)) {
				throw new IllegalStateException("Throwing argument name '" 
						+ this.throwingName + "' was not bound in advice arguments");
			} 
			else {
				Integer index = (Integer) this.argumentBindings.get(this.throwingName);
				this.discoveredThrowingType = this.aspectJAdviceMethod.getParameterTypes()[index.intValue()];				
			}
		}
		
		// configure the pointcut expression accordingly.
		configurePointcutParameters(argumentIndexOffset);
	}

	/**
	 * All parameters from argumentIndexOffset onwards are candidates for
	 * pointcut parameters - but returning and throwing vars are handled differently
	 * and must be removed from the list if present.
	 * @param argumentIndexOffset
	 */
	private void configurePointcutParameters(int argumentIndexOffset) {
		int numParametersToRemove = argumentIndexOffset;
		if (returningName != null) {
			numParametersToRemove++;
		}
		if (throwingName != null) {
			numParametersToRemove++;
		}
		String[] pointcutParameterNames = new String[this.argumentNames.length - numParametersToRemove];
		Class[] pointcutParameterTypes = new Class[pointcutParameterNames.length];
		Class[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();

		int index = 0;
		for (int i = 0; i < this.argumentNames.length; i++) {
			if (i < argumentIndexOffset) {
				continue;
			}
			if (this.argumentNames[i].equals(this.returningName) ||
				this.argumentNames[i].equals(this.throwingName)) {
				continue;
			}
			pointcutParameterNames[index] = this.argumentNames[i];
			pointcutParameterTypes[index] = methodParameterTypes[i];
			index++;
		}
		
		this.pointcutExpression.setParameterNames(pointcutParameterNames);
		this.pointcutExpression.setParameterTypes(pointcutParameterTypes);
	}
	
	/**
	 * Take the arguments at the method execution join point and output a set of arguments
	 * to the advice method
	 * @param jpMatch the join point match that matched this execution join point
	 * @param returnValue the return value from the method execution (may be null)
	 * @param t the exception thrown by the method execution (may be null)
	 * @return the empty array if there are no arguments
	 */
	protected Object[] argBinding(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable t) {
		// AMC start
		Object[] adviceInvocationArgs = new Object[this.numAdviceInvocationArguments];
		int numBound = 0;
		
		if (this.joinPointArgumentIndex != -1) {
			adviceInvocationArgs[this.joinPointArgumentIndex] = jp;
			numBound++;
		} 
		else if (this.joinPointStaticPartArgumentIndex != -1) {
			adviceInvocationArgs[this.joinPointStaticPartArgumentIndex] = jp.getStaticPart();
			numBound++;
		}
		
		if (!this.argumentBindings.isEmpty()) {
			// binding from pointcut match
			if (jpMatch != null) {
				PointcutParameter[] parameterBindings = jpMatch.getParameterBindings();
				for (int i = 0; i < parameterBindings.length; i++) {
					PointcutParameter parameter = parameterBindings[i];
					String name = parameter.getName();
					Integer index = (Integer) this.argumentBindings.get(name);
					adviceInvocationArgs[index.intValue()] = parameter.getBinding();
					numBound++;
				}
			}
			// binding from returning clause
			if (this.returningName != null) {
				Integer index = (Integer) this.argumentBindings.get(this.returningName);
				adviceInvocationArgs[index.intValue()] = returnValue;
				numBound++;
			}
			// binding from thrown exception
			if (this.throwingName != null) {
				Integer index = (Integer) this.argumentBindings.get(this.throwingName);
				adviceInvocationArgs[index.intValue()] = t;
				numBound++;
			}
		}

		if (numBound != this.numAdviceInvocationArguments) {
			throw new IllegalStateException("Required to bind " + this.numAdviceInvocationArguments
					+ " arguments, but only bound " + numBound + " (JoinPointMatch " + 
					(jpMatch == null ? "was NOT" : "WAS") + 
					" bound in invocation)");
		}
		
		return adviceInvocationArgs;
	}


	// Overridden in around advice to return proceeding join point.
	protected JoinPoint getJoinPoint() {
		return currentJoinPoint();
	}

	// Get the current join point match at the join point we are being dispatched on.
	protected JoinPointMatch getJoinPointMatch() {
		ReflectiveMethodInvocation rmi = (ReflectiveMethodInvocation) ExposeInvocationInterceptor.currentInvocation();
		return getJoinPointMatch(rmi);
	}

	// Note - can't use JoinPointMatch.getClass().getName() as the key, since
	// Spring AOP does all the matching at a join point, and then all the invocations.
	// Under this scenario, if we just use JoinPointMatch as the key, then
	// 'last man wins' which is not what we want at all.
	// Using the expression is guaranteed to be safe, since 2 identical expressions
	// are guaranteed to bind in exactly the same way.
	protected JoinPointMatch getJoinPointMatch(ReflectiveMethodInvocation rmi) {
		JoinPointMatch jpm = (JoinPointMatch) rmi.getUserAttribute(this.pointcutExpression.getExpression());
		return jpm;		
	}

	/**
	 * Invoke the advice method.
	 * @param jpMatch the JoinPointMatch that matched this execution join point
	 * @param returnValue the return value from the method execution (may be null)
	 * @param t the exception thrown by the method execution (may be null)
	 */
	protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable t) throws Throwable {
		return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, t));
	}

	// As above, but in this case we are given the join point.
	protected Object invokeAdviceMethod(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable t)
			throws Throwable {

		return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
	}

	protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
		if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
			args = null;
		}
		
		try {
			// TODO AopUtils.invokeJoinpointUsingReflection
			return this.aspectJAdviceMethod.invoke(aif.getAspectInstance(), args);
		}
		catch (IllegalArgumentException ex) {
			throw new AopConfigException("Mismatch on arguments to advice method [" + this.aspectJAdviceMethod + "]; " +
					"pointcut expression = [" + this.pointcutExpression.getPointcutExpression() + "]", ex);
		}
		catch (InvocationTargetException ex) {
			throw ex.getTargetException();
		}
	}


	public String toString() {
		return getClass().getName() + ": adviceMethod=" + this.aspectJAdviceMethod + "; " +
				"aspectName='" + this.aspectName + "'";
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -