6.5Spring的AOP的解析——寻找匹配的代理增强

 前面完成了所有增强器的解析,但是对于所有的增强器来讲,并不一定适用于当前bean,还需要进行挑选。具体的实现在findAdvisorsThatCanApply方法中实现。

    protected List<Advisor> findAdvisorsThatCanApply(
            List<Advisor> candidateAdvisors, Class beanClass, String beanName) {
            //设置当前正在创建代理的beanNAme,ThreadLocal类型的变量
        ProxyCreationContext.setCurrentProxiedBeanName(beanName);
        try {
            //过滤已经得到的advisors
            return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
        }
        finally {
            //设置当前正在创建代理的beanNAme位null,表示当前线程创建完了,可以下一个
            ProxyCreationContext.setCurrentProxiedBeanName(null);
        }
    }

继续看看findAdvisorsThatCanApply方法
先介绍一下aop中的增强类型

  • 前置增强 (org.springframework.aop.BeforeAdvice) 表示在目标方法执行前来实施增强
  • 后置增强 (org.springframework.aop.AfterReturningAdvice) 表示在目标方法执行后来实施增强
  • 环绕增强 (org.aopalliance.intercept.MethodInterceptor) 表示在目标方法执行前后同时实施增强
  • 异常抛出增强 (org.springframework.aop.ThrowsAdvice) 表示在目标方法抛出异常后来实施增强
  • 引介增强 (org.springframework.aop.introductioninterceptor) 表示在目标类中添加一些新的方法和属性

 其中,引介增强是一种特殊的增强。他可以在目标类中添加属性和方法,通过拦截定义一个接口,让目标代理实现这个接口。他的连接点是类级别的,而前面的几种则是方法级别的。

    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
        //首先出引介增强,引介增强(目标类中添加一些新的方法和属性,可以用户自己实现IntroductionAdvisor来进行自定义处理)
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
                eligibleAdvisors.add(candidate);
            }
        }
        boolean hasIntroductions = !eligibleAdvisors.isEmpty();
        for (Advisor candidate : candidateAdvisors) {
            if (candidate instanceof IntroductionAdvisor) {
                //引介增强已经处理过这里不处理
                continue;
            }
            //只处理普通增强
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }

  findAdvisorsThatCanApply函数的主要功能就是寻找所有的增强器中适用于当前class的增强器。其中匹配的主要逻辑在canApply方法中

    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
        //引介增强和普通的增强的处理不一样,对于真正的匹配在canApply中实现的
        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");
        //获取ClassFilter(过滤器限制切入点或介绍与给定目标类集的匹配)并通过需要代理的类的类名来匹配
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        }
        //获取切点的MethodMatcher方法匹配器
        MethodMatcher methodMatcher = pc.getMethodMatcher();
        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        //如果是引介增强类型的方法匹配器起则转化为引介增强的
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
            introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }
        //将需要代理的类相关的接口转化为set集合的,跟这个类所有有关的接口,父接口的接口也包括
        Set<Class> classes = new LinkedHashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
        classes.add(targetClass);
        //便利所有的class类的所有的方法,并去匹配对应的方法看是否存在对应的切点方法
        for (Class<?> clazz : classes) {
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                if ((introductionAwareMethodMatcher != null &&
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
                        methodMatcher.matches(method, targetClass)) {
                    return true;
                }
            }
        }

        return false;
    }   

 找到匹配的代理之后就是创建地代理创建代理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值