All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor Maven / Gradle / Ivy

There is a newer version: 6.1.6
Show newest version
/*
 * Copyright 2002-2020 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
 *
 *      https://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.adapter;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.aop.AfterAdvice;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
 * Interceptor to wrap an after-throwing advice.
 *
 * 

The signatures on handler methods on the {@code ThrowsAdvice} * implementation method argument must be of the form:
* * {@code void afterThrowing([Method, args, target], ThrowableSubclass);} * *

Only the last argument is required. * *

Some examples of valid methods would be: * *

public void afterThrowing(Exception ex)
*
public void afterThrowing(RemoteException)
*
public void afterThrowing(Method method, Object[] args, Object target, Exception ex)
*
public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)
* *

This is a framework class that need not be used directly by Spring users. * * @author Rod Johnson * @author Juergen Hoeller * @see MethodBeforeAdviceInterceptor * @see AfterReturningAdviceInterceptor */ public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice { private static final String AFTER_THROWING = "afterThrowing"; private static final Log logger = LogFactory.getLog(ThrowsAdviceInterceptor.class); private final Object throwsAdvice; /** Methods on throws advice, keyed by exception class. */ private final Map, Method> exceptionHandlerMap = new HashMap<>(); /** * Create a new ThrowsAdviceInterceptor for the given ThrowsAdvice. * @param throwsAdvice the advice object that defines the exception handler methods * (usually a {@link org.springframework.aop.ThrowsAdvice} implementation) */ public ThrowsAdviceInterceptor(Object throwsAdvice) { Assert.notNull(throwsAdvice, "Advice must not be null"); this.throwsAdvice = throwsAdvice; Method[] methods = throwsAdvice.getClass().getMethods(); for (Method method : methods) { if (method.getName().equals(AFTER_THROWING) && (method.getParameterCount() == 1 || method.getParameterCount() == 4)) { Class throwableParam = method.getParameterTypes()[method.getParameterCount() - 1]; if (Throwable.class.isAssignableFrom(throwableParam)) { // An exception handler to register... this.exceptionHandlerMap.put(throwableParam, method); if (logger.isDebugEnabled()) { logger.debug("Found exception handler method on throws advice: " + method); } } } } if (this.exceptionHandlerMap.isEmpty()) { throw new IllegalArgumentException( "At least one handler method must be found in class [" + throwsAdvice.getClass() + "]"); } } /** * Return the number of handler methods in this advice. */ public int getHandlerMethodCount() { return this.exceptionHandlerMap.size(); } @Override @Nullable public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (Throwable ex) { Method handlerMethod = getExceptionHandler(ex); if (handlerMethod != null) { invokeHandlerMethod(mi, ex, handlerMethod); } throw ex; } } /** * Determine the exception handle method for the given exception. * @param exception the exception thrown * @return a handler for the given exception type, or {@code null} if none found */ @Nullable private Method getExceptionHandler(Throwable exception) { Class exceptionClass = exception.getClass(); if (logger.isTraceEnabled()) { logger.trace("Trying to find handler for exception of type [" + exceptionClass.getName() + "]"); } Method handler = this.exceptionHandlerMap.get(exceptionClass); while (handler == null && exceptionClass != Throwable.class) { exceptionClass = exceptionClass.getSuperclass(); handler = this.exceptionHandlerMap.get(exceptionClass); } if (handler != null && logger.isTraceEnabled()) { logger.trace("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler); } return handler; } private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable { Object[] handlerArgs; if (method.getParameterCount() == 1) { handlerArgs = new Object[] {ex}; } else { handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex}; } try { method.invoke(this.throwsAdvice, handlerArgs); } catch (InvocationTargetException targetEx) { throw targetEx.getTargetException(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy