美文网首页
6.5Spring的AOP的解析——寻找匹配的代理增强

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

作者: szhlcy | 来源:发表于2019-02-12 11:34 被阅读0次

     前面完成了所有增强器的解析,但是对于所有的增强器来讲,并不一定适用于当前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;
        }   
    

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

    相关文章

      网友评论

          本文标题:6.5Spring的AOP的解析——寻找匹配的代理增强

          本文链接:https://www.haomeiwen.com/subject/kpiheqtx.html