栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring AOP基础组件 Advice

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring AOP基础组件 Advice

相关阅读

Spring AOP基础组件 PointcutSpring AOP基础组件 AdvisorSpring AOP基础组件 Advised 简介

表示通知的标签接口,通知的实现类可以多种,比如Interceptor;

源码
public interface Advice {

}
实现子类

BeforeAdvice 简介

前置通知的标记接口;实现子类有:MethodBeforeAdvice;
Spring目前只支持方法前置通知;

AfterAdvice 简介

后置通知的标记接口,实现子类有:AfterReturningAdvice、ThrowsAdvice;

AbstractAspectJAdvice 简介

包装AspectJ切面或者AspectJ注解标注的通知方法的AOP Advice的基础类;

核心代码
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {

    // 调用增强方法
    protected Object invokeAdviceMethod(
            @Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
            throws Throwable {

        return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
    }

    // 调用增强方法
    protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
            @Nullable Object returnValue, @Nullable Throwable t) throws Throwable {

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

    // 根据给定参数调用增强方法
    protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
        Object[] actualArgs = args;
        if (this.aspectJAdviceMethod.getParameterCount() == 0) {
            actualArgs = null;
        }
        try {
            // 反射调用增强方法
            ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
            return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
        }
        catch (IllegalArgumentException ex) {
            throw new AopInvocationException("Mismatch on arguments to advice method [" +
                    this.aspectJAdviceMethod + "]; pointcut expression [" +
                    this.pointcut.getPointcutexpression() + "]", ex);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}
AspectJMethodBeforeAdvice 简介

包装AspectJ前置通知方法的Spring AOP Advice;

核心代码
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {

    @Override
    public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }

    @Override
    public boolean isBeforeAdvice() {
        return true;
    }

    @Override
    public boolean isAfterAdvice() {
        return false;
    }
}
AspectJAfterAdvice 简介

包装AspectJ最终通知方法的Spring AOP Advice;

核心代码
public class AspectJAfterAdvice extends AbstractAspectJAdvice
        implements MethodInterceptor, AfterAdvice, Serializable {

    @Override
    @Nullable
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            return mi.proceed();
        }
        finally {
            // 不管是否正常返回都会执行通知
            invokeAdviceMethod(getJoinPointMatch(), null, null);
        }
    }

    @Override
    public boolean isBeforeAdvice() {
        return false;
    }

    @Override
    public boolean isAfterAdvice() {
        return true;
    }
}
AspectJAfterReturningAdvice 简介

包装AspectJ后置通知方法的Spring AOP Advice;

核心代码
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
        implements AfterReturningAdvice, AfterAdvice, Serializable {

    @Override
    public boolean isBeforeAdvice() {
        return false;
    }

    @Override
    public boolean isAfterAdvice() {
        return true;
    }

    @Override
    public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
        // 根据返回值判断是否调用
        if (shouldInvokeOnReturnValueOf(method, returnValue)) {
            invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
        }
    }

    private boolean shouldInvokeOnReturnValueOf(Method method, @Nullable Object returnValue) {
        Class type = getDiscoveredReturningType();
        Type genericType = getDiscoveredReturningGenericType();
        // If we aren't dealing with a raw type, check if generic parameters are assignable.
        // 判断返回值类型是否匹配,如果返回值类型是泛型类型,则泛型参数也要匹配
        return (matchesReturnValue(type, method, returnValue) &&
                (genericType == null || genericType == type ||
                        TypeUtils.isAssignable(genericType, method.getGenericReturnType())));
    }

    private boolean matchesReturnValue(Class type, Method method, @Nullable Object returnValue) {
        if (returnValue != null) {
            // 返回值是否是指定类型type
            return ClassUtils.isAssignablevalue(type, returnValue);
        }
        else if (Object.class == type && void.class == method.getReturnType()) {
            // 方法无返回值也会匹配Object类型
            return true;
        }
        else {
            // 方法返回值类型是否匹配指定类型type
            return ClassUtils.isAssignable(type, method.getReturnType());
        }
    }
}
AspectJAfterThrowingAdvice 简介

包装AspectJ抛出异常通知方法的Spring AOP Advice;

核心代码
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
        implements MethodInterceptor, AfterAdvice, Serializable {

    @Override
    public boolean isBeforeAdvice() {
        return false;
    }

    @Override
    public boolean isAfterAdvice() {
        return true;
    }

    @Override
    public void setThrowingName(String name) {
        setThrowingNameNoCheck(name);
    }

    @Override
    @Nullable
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            return mi.proceed();
        }
        catch (Throwable ex) {
            // 根据异常类型判断是否调用
            if (shouldInvokeOnThrowing(ex)) {
                invokeAdviceMethod(getJoinPointMatch(), null, ex);
            }
            throw ex;
        }
    }

    private boolean shouldInvokeOnThrowing(Throwable ex) {
        // 当前发生的异常是否匹配指定异常类型
        return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
    }
}
AspectJAroundAdvice 简介

包装AspectJ环绕通知方法的Spring AOP Advice;

核心代码
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {

    @Override
    public boolean isBeforeAdvice() {
        return false;
    }

    @Override
    public boolean isAfterAdvice() {
        return false;
    }

    @Override
    protected boolean supportsProceedingJoinPoint() {
        return true;
    }

    @Override
    @Nullable
    public Object invoke(MethodInvocation mi) throws Throwable {
        if (!(mi instanceof ProxyMethodInvocation)) {
            throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
        }
        ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
        ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
        JoinPointMatch jpm = getJoinPointMatch(pmi);
        return invokeAdviceMethod(pjp, jpm, null, null);
    }

    protected ProceedingJoinPoint lazyGetProceedingJoinPoint(ProxyMethodInvocation rmi) {
        return new MethodInvocationProceedingJoinPoint(rmi);
    }
}
MethodInterceptor 简介

在到达目标的途中拦截接口的调用,子类实现在接口调用之前和之后执行额外处理逻辑;

核心代码
@FunctionalInterface
public interface MethodInterceptor extends Interceptor {

    // 调用方法调用,可以在方法调用之前和之后执行额外逻辑
    @Nullable
    Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;
}
ConstructorInterceptor 简介

拦截构造方法,子类实现在构造方法调用之前和之后执行额外处理逻辑;

核心方法
public interface ConstructorInterceptor extends Interceptor  {

    // 调用构造方法调用,可以在构造方法调用之前和之后执行额外逻辑
    @Nonnull
    Object construct(ConstructorInvocation invocation) throws Throwable;
}
MethodBeforeAdviceInterceptor 简介

包装MethodBeforeAdvice的Interceptor;

核心代码
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

    // 前置通知
    private final MethodBeforeAdvice advice;


    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        // 校验前置通知
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    @Override
    @Nullable
    public Object invoke(MethodInvocation mi) throws Throwable {
        // 先执行前置通知逻辑
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        // 再执行方法调用
        return mi.proceed();
    }
}
AfterReturningAdviceInterceptor 简介

包装AfterReturningAdvice的Interceptor;

核心代码
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

    // 后置通知
    private final AfterReturningAdvice advice;


    public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
        // 校验后置通知
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    @Override
    @Nullable
    public Object invoke(MethodInvocation mi) throws Throwable {
        // 先执行方法调用
        Object retVal = mi.proceed();
        // 再执行后置通知逻辑
        this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
        return retVal;
    }
}
ThrowsAdviceInterceptor 简介

包装ThrowsAdvice的Interceptor;
ThrowsAdvice实现子类中的异常处理方法的签名必须是以下格式:
void afterThrowing([Method, args, target], ThrowableSubclass);
比如:

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)
核心代码
public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {

    private static final String AFTER_THROWING = "afterThrowing";

    // 抛出异常增强
    private final Object throwsAdvice;

    // 缓存异常处理方法,以异常类型为KEY
    private final Map, Method> exceptionHandlerMap = new HashMap<>();


    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)) {
                    // 缓存异常处理方法,方便直接根据异常类型直接获取异常处理方法
                    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() + "]");
        }
    }

    @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;
        }
    }

    @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();
        }
    }
}
AsyncExecutionInterceptor 简介

使用AsyncTaskExecutor异步执行方法调用的AOP MethodInterceptor;

核心代码
public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport implements MethodInterceptor, Ordered {

    @Override
    @Nullable
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
        Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
        final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

        // 获取方法调用对应的执行器
        AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
        if (executor == null) {
            // 执行器必须存在,否则直接抛出异常
            throw new IllegalStateException(
                    "No executor specified and no default executor set on AsyncExecutionInterceptor either");
        }

        // 封装方法调用为异步任务
        Callable task = () -> {
            try {
                // 调用方法调用
                Object result = invocation.proceed();
                if (result instanceof Future) {
                    // 等待返回值
                    return ((Future) result).get();
                }
            }
            catch (ExecutionException ex) {
                // 异常处理
                handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
            }
            catch (Throwable ex) {
                // 异常处理
                handleError(ex, userDeclaredMethod, invocation.getArguments());
            }
            return null;
        };

        // 提交异步任务
        return doSubmit(task, executor, invocation.getMethod().getReturnType());
    }
}
 
CacheInterceptor 
简介 

支持Spring声明式缓存管理的AOP MethodInterceptor;

核心代码
public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable {

    @Override
    @Nullable
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        Method method = invocation.getMethod();

        // 封装方法调用为缓存操作调用
        CacheOperationInvoker aopAllianceInvoker = () -> {
            try {
                // 调用方法调用
                return invocation.proceed();
            }
            catch (Throwable ex) {
                throw new CacheOperationInvoker.ThrowableWrapper(ex);
            }
        };

        // 获取目标对象
        Object target = invocation.getThis();
        Assert.state(target != null, "Target must not be null");
        try {
            // 执行缓存操作调用
            return execute(aopAllianceInvoker, target, method, invocation.getArguments());
        }
        catch (CacheOperationInvoker.ThrowableWrapper th) {
            throw th.getOriginal();
        }
    }
}
TransactionInterceptor 简介

支持Spring声明式事务管理的AOP MethodInterceptor;

核心代码
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

    @Override
    @Nullable
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // Work out the target class: may be {@code null}.
        // The TransactionAttributeSource should be passed the target class
        // as well as the method, which may be from an interface.
        Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

        // Adapt to TransactionAspectSupport's invokeWithinTransaction...
        return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
            @Override
            @Nullable
            public Object proceedWithInvocation() throws Throwable {
                // 调用方法调用
                return invocation.proceed();
            }
            @Override
            public Object getTarget() {
                return invocation.getThis();
            }
            @Override
            public Object[] getArguments() {
                return invocation.getArguments();
            }
        });
    }
}
AbstractTraceInterceptor 简介

日志跟踪的基础MethodInterceptor实现;

核心代码
public abstract class AbstractTraceInterceptor implements MethodInterceptor, Serializable {

    @Override
    @Nullable
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // 获取Log
        Log logger = getLoggerForInvocation(invocation);
        if (isInterceptorEnabled(invocation, logger)) {
            // 日志跟踪调用
            return invokeUnderTrace(invocation, logger);
        }
        else {
            // 调用方法调用
            return invocation.proceed();
        }
    }

    // 实现子类确保方法调用一定被调用,可以在方法调用前后执行日志跟踪
    @Nullable
    protected abstract Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable;
}
ExposeInvocationInterceptor 简介

将当前MethodInvocation放到当前线程对应的ThreadLocalMap里,当作一个线程本地变量;
如果使用的话,ExposeInvocationInterceptor正常都是在拦截器链首位;

核心代码
public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {

    // 单例
    public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();

    private static final ThreadLocal invocation =
            new NamedThreadLocal<>("Current AOP method invocation");


    // 获取当前MethodInvocation
    public static MethodInvocation currentInvocation() throws IllegalStateException {
        MethodInvocation mi = invocation.get();
        if (mi == null) {
            throw new IllegalStateException(
                    "No MethodInvocation found: Check that an AOP invocation is in progress and that the " +
                    "ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that " +
                    "advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor! " +
                    "In addition, ExposeInvocationInterceptor and ExposeInvocationInterceptor.currentInvocation() " +
                    "must be invoked from the same thread.");
        }
        return mi;
    }


    // 确保单例
    private ExposeInvocationInterceptor() {
    }

    @Override
    @Nullable
    public Object invoke(MethodInvocation mi) throws Throwable {
        // 缓存当前MethodInvocation
        MethodInvocation oldInvocation = invocation.get();
        // 更新当前MethodInvocation
        invocation.set(mi);
        try {
            // 调用方法调用
            return mi.proceed();
        }
        finally {
            // 还原当前MethodInvocation
            invocation.set(oldInvocation);
        }
    }
}
DelegatingIntroductionInterceptor 简介

支持引介功能的AOP MethodInterceptor;

核心代码
public class DelegatingIntroductionInterceptor extends IntroductionInfoSupport
        implements IntroductionInterceptor {

    @Override
    @Nullable
    public Object invoke(MethodInvocation mi) throws Throwable {
        if (isMethodOnIntroducedInterface(mi)) {
            Object retVal = AopUtils.invokeJoinpointUsingReflection(this.delegate, mi.getMethod(), mi.getArguments());

            // 如果返回值就是delegate本身,那么真实想返回的应该是proxy
            if (retVal == this.delegate && mi instanceof ProxyMethodInvocation) {
                Object proxy = ((ProxyMethodInvocation) mi).getProxy();
                if (mi.getMethod().getReturnType().isInstance(proxy)) {
                    retVal = proxy;
                }
            }
            return retVal;
        }

        return doProceed(mi);
    }

    @Nullable
    protected Object doProceed(MethodInvocation mi) throws Throwable {
        // 调用方法调用
        return mi.proceed();
    }
}
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号