梳理 Spring AOP

定义案例

@Component
@Aspect
@Slf4j
public class SpringLearnAop  {
    @Pointcut("execution(* com.example.springcorelearn.answer..*(..))")
    public void definitionPointCut() {
    }
    @AfterReturning("definitionPointCut()")
    public void afterReturningProcess() {
        log.info("结束了。。。。");
    }

    @After("definitionPointCut()")
    public void afterProcess() {
        log.info("结束了。。。。");
    }
    @AfterThrowing
    public void afterThrowing(){
        log.info("异常错误");
    }

    @Before("definitionPointCut()")
    public void beforeProcess() {
        log.info("想到我了");
    }

    @Around("definitionPointCut()")
    public Object around(ProceedingJoinPoint joinPoint){
        log.info("around start....");
        try {
            return joinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
            log.info("around end....");

        }

    }

}

元数据注解定义

连接点:PointCut

增强通知

  1. Around

  1. Befroe

  1. After

  1. AfterReturning

  1. AfterThrowing

工具类

BeanFactoryAspectJAdvisorsBuilder

ReflectiveAspectJAdvisorFactory

重点成员变量

adviceMethodComparator

源码
        // Note: although @After is ordered before @AfterReturning and @AfterThrowing,
        // an @After advice method will actually be invoked after @AfterReturning and
        // @AfterThrowing methods due to the fact that AspectJAfterAdvice.invoke(MethodInvocation)
        // invokes proceed() in a `try` block and only invokes the @After advice method
        // in a corresponding `finally` block.
        Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
                new InstanceComparator<>(
                        Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
                (Converter<Method, Annotation>) method -> {
                    AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
                    return (ann != null ? ann.getAnnotation() : null);
                });
        Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
        adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);
分析

保证增强通知元数据方法按顺序排序

  1. Around

  1. Before

  1. After

  1. AfterReturning

  1. AfterThrowing

重点方法
getAdvisors

获得切面配置类的增强通知方法。并排序。

增强通知类

AbstractAspectJAdvice

所有的Advice类都是继承了该抽象类。

重点方法
invokeAdviceMethodWithGivenArgs
源码
    protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
        Object[] actualArgs = args;
        if (this.aspectJAdviceMethod.getParameterCount() == 0) {
            actualArgs = null;
        }
       
            ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
            //执行元数据配置通知方法 
            return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
        }
       
    }

AspectJAroundAdvice

重点实现了MethodInvocation接口

    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 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

重点没有实现MethodInvocation接口

源码

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

AsepctJAfterAdvice

重点其实现了MethodInvocation接口

源码

    @Override
    @Nullable
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            return mi.proceed();
        }
        finally {
            invokeAdviceMethod(getJoinPointMatch(), null, null);
        }
    }
分析

使用 try finally 语句。保证invokeAdviceMethod方法一定会执行并且最后执行。

AspectJAfterReturningAdvice

重点没有实现MethodInvocation接口

源码

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

AspectJAfterThrowingAdvice

重点其实现了MethodInvocation接口

源码

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

重新其父类的invoke方法。捕获catch异常,执行父类的invokeAdviceMethod

AdviceAdpater

适配转化成MethodInterceptor

由于AsepctJAroundAdvice、AsepctJAfterAdvice还有AspectJAfterThrowingAdvice已经实现了MethodInterceptor接口不需要再做适配

  • MethodBeforeAdviceAdapter

  • AfterReturningAdeviceAdapter

  • ThrowingAdapter

AdvisorAdapterRegistry

DefaultAdvisorAdapterRegistry

GlobalAdvisorAdpatorRegistry

MethodMatcher

方法匹配器

AspectJExpressionPointcut 连接点拦截

MethodInterceptor

AsepctJAroundAdvice和AsepctJAfterAdvice已经实现了MethodInterceptor接口

MethodBeforeAdviceInterceptor

源码
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        return mi.proceed();
    }
分析

最容易理解。回调执行前

AfterReturningAdviceInterceptor

    @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

ReflectiveMethodInvocation

重点方法
proceed

使用责任链模式调用切面方法。

inovkeJoinPoint

执行连接点方法

AopProxy

  • CglibAopProxy

  • JdkDynamicAopProxy

AnnotationAwareAspectJAutoProxyCreator

重点方法

buildAspectJAdvisors 查询切面配置类和收集切面信息。

findCandidateAdvisors 查找可用的切面

实例化前处理器

AbstractAutoProxyCreator#postProcessBeforeInstantiation

  1. 查找切面元数据配置类

  1. 解决切面元数据配置类并将增强通知转化成AbstractAspectJAdvice子类。

  1. 包装成InstantiationModelAwarePointcutAdvisorImpl将增强通知保存到BeanFactoryAspectJAdvisorsBuilder.aspectJFactoryCache.aspectJFactoryCache

InstantiationModelAwarePointcutAdvisorImpl 类图

说明其实现了PointcutAdvisors接口。


初始化后处理器

AbstractAutoProxyCreator#postProcessAfterInitialization

核心逻辑是:创建代理若匹配条件。 AbstractAutoProxyCreator#wrapIfNecessary

匹配条件

AbstractAdvisorAutoProxyCreator#findCandidate

实例前处理器已经调用过该方法。查找可用切面最终保存到BeanFactoryAspectJAdvisorBuilder.aspectJFactoryCache

AopUtils#findAdvisorsThatCanApply

遍历BeanFactoryAspectJAdvisorsBuilder.aspectJFactoryCache.aspectJFactoryCache

并验证切面是否是PointcutAdvisor子类。并且检查切面是否可以应用在目标类的方法上。

源码
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new ArrayList<>();
        for (Advisor candidate : candidateAdvisors) {
            //由于candidate 都是PointcutAdvior子类,所以不会走这个逻辑
            if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor) {
                // already processed
                continue;
            }
            //进入这个分支
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }
    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
//由于candidate 都是PointcutAdvior子类,所以不会走这个逻辑
        if (advisor instanceof IntroductionAdvisor) {
            return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
        }
        else if (advisor instanceof PointcutAdvisor) {
            PointcutAdvisor pca = (PointcutAdvisor) advisor;
            return canApply(pca.getPointcut(), targetClass, hasIntroductions);
        }
        else {
            // It doesn't have a pointcut so we assume it applies.
            return true;
        }
    }
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        Assert.notNull(pc, "Pointcut must not be null");
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }
       //methodMatcher 是AspectJExpressionPointcut类型。
        MethodMatcher methodMatcher = pc.getMethodMatcher();
//不会走这个条件分支
        if (methodMatcher == MethodMatcher.TRUE) {
            // No need to iterate the methods if we're matching any method anyway...
            return true;
        }

        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
//由于AspectJExpressionPointcut是IntroductionAwareMethodMatcher子类,会走个分支。
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        Set<Class<?>> classes = new LinkedHashSet<>();
        if (!Proxy.isProxyClass(targetClass)) {
            classes.add(ClassUtils.getUserClass(targetClass));
        }
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        for (Class<?> clazz : classes) {
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            for (Method method : methods) {
                if (introductionAwareMethodMatcher != null ?
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }
        }

        return false;
    }

创建代理

代理工厂 ProxyFactory
 createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
ProxyFactory类图

创建代理 AopFactory
getAopProxyFactory().createAopProxy(this);
createAopProxy

DefaultAopProxyFactory.createAopProxy

若proxy-target-class =true 使用CglibAopFactory否则使用JdkDynamicAopFactory

执行代理方法

JdkDynamicAopFactory#invoke

源码
    private final AdvisedSupport advised;
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // Get the interception chain for this method.
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// We need to create a method invocation...
                MethodInvocation invocation =
                        new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // Proceed to the joinpoint through the interceptor chain.
                retVal = invocation.proceed();
}
分析

看getInterceptorsAndDynamicInterceptionAdvice顾名思义获取切面增强通知调用链。

调用ReflectiveMethodInvocation.proceed 执行。

AdvisedSupport#getInterceptorAndDynamicInterceptionAdvice

    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
        MethodCacheKey cacheKey = new MethodCacheKey(method);
        List<Object> cached = this.methodCache.get(cacheKey);
        if (cached == null) {
//核心代码,往下看
            cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                    this, method, targetClass);
            this.methodCache.put(cacheKey, cached);
        }
        return cached;
    }

DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice

    @Override
    public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Method method, @Nullable Class<?> targetClass) {

        // This is somewhat tricky... We have to process introductions first,
        // but we need to preserve order in the ultimate list.
       //读取切面适配器注册中心实例
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        Advisor[] advisors = config.getAdvisors();
        List<Object> interceptorList = new ArrayList<>(advisors.length);
        Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        Boolean hasIntroductions = null;

        for (Advisor advisor : advisors) {
            if (advisor instanceof PointcutAdvisor) {
                // Add it conditionally.
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                    //方法匹配器
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    //是否能连接这个方法
                    match = mm.matches(method, actualClass);
                    //将增强通知转化成方法拦截器 
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    if (match) {
                       interceptorList.addAll(Arrays.asList(interceptors)); 
                     } 
                                          
                    
                }
            }
           //... 删除部分代码。       
           //由于Advisor 都是PointCutAdvisor实现类
        }

        return interceptorList;
    }

ReflectiveMethodInvocation#process

    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);
       //删除无关代码
            // 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);
        
    }

AnnotationAwareApsectJAutoProxyCreator#findCandidateAdvisors

    @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
        if (this.aspectJAdvisorsBuilder != null) {
            advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
    }

BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvsiors

查询切面配置类缓存到内部advisorsCache

    private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache = new ConcurrentHashMap<>();

    public List<Advisor> buildAspectJAdvisors() {
        List<String> aspectNames = this.aspectBeanNames;

        if (aspectNames == null) {
            synchronized (this) {
                aspectNames = this.aspectBeanNames;
                if (aspectNames == null) {
                    List<Advisor> advisors = new ArrayList<>();
                    aspectNames = new ArrayList<>();
                //遍历所有的bean。
                    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            this.beanFactory, Object.class, true, false);
                    for (String beanName : beanNames) {
                        if (!isEligibleBean(beanName)) {
                            continue;
                        }
                        // We must be careful not to instantiate beans eagerly as in this case they
                        // would be cached by the Spring container but would not have been weaved.
                        Class<?> beanType = this.beanFactory.getType(beanName, false);
                        if (beanType == null) {
                            continue;
                        }
//验证是否是Aspect配置类
                        if (this.advisorFactory.isAspect(beanType)) {
                            aspectNames.add(beanName);
                            AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                                MetadataAwareAspectInstanceFactory factory =
                                        new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                                List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                                if (this.beanFactory.isSingleton(beanName)) {
                                    this.advisorsCache.put(beanName, classAdvisors);
                                }
                                else {
                                    this.aspectFactoryCache.put(beanName, factory);
                                }
                                advisors.addAll(classAdvisors);
                            }
                            else {
                                //...
                                 
                            }
                        }
                    }

                }
            }
        }
       //.....

        return advisors;
    }

ReflectiveAspectJAdvisorsFactory.getAdvice

将注解转化成增强通知类Advice

@Override
    @Nullable
    public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }
        AbstractAspectJAdvice springAdvice;

        switch (aspectJAnnotation.getAnnotationType()) {
            case AtPointcut:
                if (logger.isDebugEnabled()) {
                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }
                return null;
            case AtAround:
                springAdvice = new AspectJAroundAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtBefore:
                springAdvice = new AspectJMethodBeforeAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfter:
                springAdvice = new AspectJAfterAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            case AtAfterReturning:
                springAdvice = new AspectJAfterReturningAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                    springAdvice.setReturningName(afterReturningAnnotation.returning());
                }
                break;
            case AtAfterThrowing:
                springAdvice = new AspectJAfterThrowingAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                    springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
                }
                break;
            default:
                throw new UnsupportedOperationException(
                        "Unsupported advice type on method: " + candidateAdviceMethod);
        }

        // Now to configure the advice...
        springAdvice.setAspectName(aspectName);
        springAdvice.setDeclarationOrder(declarationOrder);
        String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
        if (argNames != null) {
            springAdvice.setArgumentNamesFromStringArray(argNames);
        }
        springAdvice.calculateArgumentBindings();

        return springAdvice;
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jiguansheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值