|
Spring Framework example source code file (ReflectiveMethodInvocation.java)
The Spring Framework ReflectiveMethodInvocation.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.framework; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.ProxyMethodInvocation; import org.springframework.aop.support.AopUtils; /** * Spring's implementation of the AOP Alliance * {@link org.aopalliance.intercept.MethodInvocation} interface, * implementing the extended * {@link org.springframework.aop.ProxyMethodInvocation} interface. * * <p>Invokes the target object using reflection. Subclasses can override the * {@link #invokeJoinpoint()} method to change this behavior, so this is also * a useful base class for more specialized MethodInvocation implementations. * * <p>It is possible to clone an invocation, to invoke {@link #proceed()} * repeatedly (once per clone), using the {@link #invocableClone()} method. * It is also possible to attach custom attributes to the invocation, * using the {@link #setUserAttribute} / {@link #getUserAttribute} methods. * * <p>NOTE: This class is considered internal and should not be * directly accessed. The sole reason for it being public is compatibility * with existing framework integrations (e.g. Pitchfork). For any other * purposes, use the {@link ProxyMethodInvocation} interface instead. * * @author Rod Johnson * @author Juergen Hoeller * @author Adrian Colyer * @see #invokeJoinpoint * @see #proceed * @see #invocableClone * @see #setUserAttribute * @see #getUserAttribute */ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable { protected final Object proxy; protected final Object target; protected final Method method; protected Object[] arguments; private final Class targetClass; /** * Lazily initialized map of user-specific attributes for this invocation. */ private Map userAttributes; /** * List of MethodInterceptor and InterceptorAndDynamicMethodMatcher * that need dynamic checks. */ protected final List interceptorsAndDynamicMethodMatchers; /** * Index from 0 of the current interceptor we're invoking. * -1 until we invoke: then the current interceptor. */ private int currentInterceptorIndex = -1; /** * Construct a new ReflectiveMethodInvocation with the given arguments. * @param proxy the proxy object that the invocation was made on * @param target the target object to invoke * @param method the method to invoke * @param arguments the arguments to invoke the method with * @param targetClass the target class, for MethodMatcher invocations * @param interceptorsAndDynamicMethodMatchers interceptors that should be applied, * along with any InterceptorAndDynamicMethodMatchers that need evaluation at runtime. * MethodMatchers included in this struct must already have been found to have matched * as far as was possibly statically. Passing an array might be about 10% faster, * but would complicate the code. And it would work only for static pointcuts. */ protected ReflectiveMethodInvocation( Object proxy, Object target, Method method, Object[] arguments, Class targetClass, List interceptorsAndDynamicMethodMatchers) { this.proxy = proxy; this.target = target; this.targetClass = targetClass; this.method = method; this.arguments = arguments; this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers; } public final Object getProxy() { return this.proxy; } public final Object getThis() { return this.target; } public final AccessibleObject getStaticPart() { return this.method; } /** * Return the method invoked on the proxied interface. * May or may not correspond with a method invoked on an underlying * implementation of that interface. */ public final Method getMethod() { return this.method; } public final Object[] getArguments() { return (this.arguments != null ? this.arguments : new Object[0]); } public void setArguments(Object[] arguments) { this.arguments = arguments; } public Object proceed() throws Throwable { // We start with an index of -1 and increment early. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } } /** * Invoke the joinpoint using reflection. * Subclasses can override this to use custom invocation. * @return the return value of the joinpoint * @throws Throwable if invoking the joinpoint resulted in an exception */ protected Object invokeJoinpoint() throws Throwable { return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments); } /** * This implementation returns a shallow copy of this invocation object, * including an independent copy of the original arguments array. * <p>We want a shallow copy in this case: We want to use the same interceptor * chain and other object references, but we want an independent value for the * current interceptor index. * @see java.lang.Object#clone() */ public MethodInvocation invocableClone() { Object[] cloneArguments = null; if (this.arguments != null) { // Build an independent copy of the arguments array. cloneArguments = new Object[this.arguments.length]; System.arraycopy(this.arguments, 0, cloneArguments, 0, this.arguments.length); } return invocableClone(cloneArguments); } /** * This implementation returns a shallow copy of this invocation object, * using the given arguments array for the clone. * <p>We want a shallow copy in this case: We want to use the same interceptor * chain and other object references, but we want an independent value for the * current interceptor index. * @see java.lang.Object#clone() */ public MethodInvocation invocableClone(Object[] arguments) { // Force initialization of the user attributes Map, // for having a shared Map reference in the clone. if (this.userAttributes == null) { this.userAttributes = new HashMap(); } // Create the MethodInvocation clone. try { ReflectiveMethodInvocation clone = (ReflectiveMethodInvocation) clone(); clone.arguments = arguments; return clone; } catch (CloneNotSupportedException ex) { throw new IllegalStateException( "Should be able to clone object of type [" + getClass() + "]: " + ex); } } public void setUserAttribute(String key, Object value) { if (value != null) { if (this.userAttributes == null) { this.userAttributes = new HashMap(); } this.userAttributes.put(key, value); } else { if (this.userAttributes != null) { this.userAttributes.remove(key); } } } public Object getUserAttribute(String key) { return (this.userAttributes != null ? this.userAttributes.get(key) : null); } /** * Return user attributes associated with this invocation. * This method provides an invocation-bound alternative to a ThreadLocal. * <p>This map is initialized lazily and is not used in the AOP framework itself. * @return any user attributes associated with this invocation * (never <code>null) */ public Map getUserAttributes() { if (this.userAttributes == null) { this.userAttributes = new HashMap(); } return this.userAttributes; } public String toString() { // Don't do toString on target, it may be proxied. StringBuffer sb = new StringBuffer("ReflectiveMethodInvocation: "); sb.append(this.method).append("; "); if (this.target == null) { sb.append("target is null"); } else { sb.append("target is of class [").append(this.target.getClass().getName()).append(']'); } return sb.toString(); } } Other Spring Framework examples (source code examples)Here is a short list of links related to this Spring Framework ReflectiveMethodInvocation.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.