`

spring AOP源码分析之拦截器

阅读更多
我们都知道在spring AOP中产生代理对象的方式有jdk和cglib的方式生成,无论那种方式,AOP的拦截的处理都是通过ReflectiveMethodInvocation中的proceed方法
其方法的源码如下:
  public Object proceed()
        throws Throwable
    {
        //如果拦截器迭代完毕,这里开始调用目标方法
        if(currentInterceptorIndex == interceptorsAndDynamicMethodMatchers.size() - 1)
            return invokeJoinpoint();
        //从拦截器的集合中获取拦截器
        Object interceptorOrInterceptionAdvice = interceptorsAndDynamicMethodMatchers.get(++currentInterceptorIndex);
        //判断如果是该类型的
        if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher)
        {
            InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
            //那么对方法进行匹配
            if(dm.methodMatcher.matches(method, targetClass, arguments))
                return dm.interceptor.invoke(this);
            else
                //否则进行递归调用
                return proceed();
        } else
        {
            //如果是interceptor,直接调用这个interceptor对应的方法  
            return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
        }
    }

那么这个拦截器链的集合是如何产生的呢?
由于AopFactoryBean是继承AdvisedSupport我们在看下AdvisedSupport中的getInterceptorsAndDynamicInterceptionAdvice方法
//获取拦截器
public List getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass)
    {
        MethodCacheKey cacheKey = new MethodCacheKey(method);
        List cached = (List)methodCache.get(cacheKey);
        if(cached == null)
        {
            //拦截器链工厂获取
            cached = advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
            methodCache.put(cacheKey, cached);
        }
        return cached;
    }
获取拦截器链的工作是由配置好的advisorChainFactory来完成的,在这里advisorChainFactory被配置成一个DefaultAdvisorChainFactory对象,在DefaultAdvisorChainFactory中getInterceptorsAndDynamicInterceptionAdvice方法来获取,源码如下:
public List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class targetClass)
    {
       //定义拦截器链数组的大小
        List interceptorList = new ArrayList(config.getAdvisors().length);
        boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);
        //这里采用的简单工厂的方式产生AdvisorAdapterRegistry对象,而该接口的实现类为DefaultAdvisorAdapterRegistry
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        org.springframework.aop.Advisor aadvisor[];
        int j = (aadvisor = config.getAdvisors()).length;
        for(int i = 0; i < j; i++)
        {
            org.springframework.aop.Advisor advisor = aadvisor[i];
            if(advisor instanceof PointcutAdvisor)
            {
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor)advisor;
                if(config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass))
                {
                    org.aopalliance.intercept.MethodInterceptor interceptors[] = registry.getInterceptors(advisor);
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    if(MethodMatchers.matches(mm, method, targetClass, hasIntroductions))
                        if(mm.isRuntime())
                        {
                            org.aopalliance.intercept.MethodInterceptor amethodinterceptor[];
                            int l = (amethodinterceptor = interceptors).length;
                            for(int k = 0; k < l; k++)
                            {
                                org.aopalliance.intercept.MethodInterceptor interceptor = amethodinterceptor[k];
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                            }

                        } else
                        {
                            interceptorList.addAll((Collection)Arrays.asList(interceptors));
                        }
                }
            } else
            if(advisor instanceof IntroductionAdvisor)
            {
                IntroductionAdvisor ia = (IntroductionAdvisor)advisor;
                if(config.isPreFiltered() || ia.getClassFilter().matches(targetClass))
                {
                    org.aopalliance.intercept.Interceptor interceptors[] = registry.getInterceptors(advisor);
                    interceptorList.addAll((Collection)Arrays.asList(interceptors));
                }
            } else
            {
                org.aopalliance.intercept.Interceptor interceptors[] = registry.getInterceptors(advisor);
                interceptorList.addAll((Collection)Arrays.asList(interceptors));
            }
        }

        return interceptorList;
    }

从上述源码可知:DefaultAdvisorChainFactory会通过一个AdivesorAdatperRegistry来实现拦截器的注册,而这个AdivesorAdatperRegistry对象的advice通知的知入功能起了很大的作用。


Advice通知的实现
我们在看下DefaultAdvisorAdapterRegistry中的getInterceptors方法

//通知适配器集合
private final List adapters = new ArrayList(3);

public MethodInterceptor[] getInterceptors(Advisor advisor)
        throws UnknownAdviceTypeException
    {
        List interceptors = new ArrayList(3);
        //从通知器中获取通知
        Advice advice = advisor.getAdvice();
        if(advice instanceof MethodInterceptor)
            interceptors.add((MethodInterceptor)advice);
        
        for(Iterator iterator = adapters.iterator(); iterator.hasNext();)
        {
            //循环所有的适配器通知
            AdvisorAdapter adapter = (AdvisorAdapter)iterator.next();
            if(adapter.supportsAdvice(advice))
                interceptors.add(adapter.getInterceptor(advisor));
        }

        if(interceptors.isEmpty())
            throw new UnknownAdviceTypeException(advisor.getAdvice());
        else
            return (MethodInterceptor[])interceptors.toArray(new MethodInterceptor[interceptors.size()]);
    }

关于通知适配器集合的初始化,通过构造函数注册
//注册advice适配器
public DefaultAdvisorAdapterRegistry()
{
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
//注册方法
public void registerAdvisorAdapter(AdvisorAdapter adapter)
{
        adapters.add(adapter);
}

我们在看一个advice适配器具体实现例如MethodBeforeAdviceAdapter源码
class MethodBeforeAdviceAdapter
    implements AdvisorAdapter, Serializable
{

    MethodBeforeAdviceAdapter()
    {
    }

    public boolean supportsAdvice(Advice advice)
    {
        return advice instanceof MethodBeforeAdvice;
    }

    public MethodInterceptor getInterceptor(Advisor advisor)
    {
        //从中获取advice
        MethodBeforeAdvice advice = (MethodBeforeAdvice)advisor.getAdvice();
        //返回拦截器
        return new MethodBeforeAdviceInterceptor(advice);
    }
}

分享到:
评论

相关推荐

    spring源码分析(1-10)

    Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源代码解析(九):Spring Acegi框架鉴权的实现 Spring源代码解析(十):Spring Acegi框架授权...

    spring源码分析

    Spring源代码解析(七):Spring AOP中对拦截器调用的实现 8. Spring源代码解析(八):Spring驱动Hibernate的实现 9.Spring源代码解析(九):Spring Acegi框架鉴权的实现 10. Spring源代码解析(十):Spring ...

    Spring源码学习文档,绝对值得好好研究~~

    Spring源代码解析(七):Spring AOP中对拦截器调用的实现.doc Spring源代码解析(八):Spring驱动Hibernate的实现.doc Spring源代码解析(九):Spring Acegi框架鉴权的实现.doc Spring源代码解析(十):Spring ...

    Spring源代码解析

    Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源代码解析(九):Spring Acegi框架鉴权的实现 Spring源代码解析(十):Spring Acegi框架授权...

    开发者突击·精通AOP整合应用开发 源码

    讲解了3种AOP的开发方式,即使用@Aspect注释符、基于Schema的配置的开发方式和Spring API的开发方式,最后在实际的Java EE项目中实现5种Spring AOP功能(日志记录器、性能分析器、权限检查拦截器、异常监视器、在线...

    深入理解Spring声明式事务:源码分析与应用实践

    在Spring中,事务管理是通过一系列的拦截器和事务管理器来实现的。当一个被@Transactional注解的方法被调用时,Spring会创建一个代理来包装该方法,确保事务的正确开始和结束。这种代理机制基于Spring AOP实现,能够...

    SSH框架实现BBS完整版

    该文档是SSH框架为基础实现的BBS论坛。其中有整合好的全面的SSH jar包,BBS前台,后台源码,这个小系统的报告,数据库关系分析等。 以下内容摘自报告目录部分(希望...4.14 根据权限定义拦截器 4.15 测试系统相应的功能

    SSH框架实现BBS完整版.2018_03_16

    该文档是SSH框架为基础实现的BBS论坛。其中有整合好的全面的SSH jar包,BBS前台,后台源码,这个小系统的报告,数据库关系分析等。 以下内容摘自报告目录部分(希望...4.14 根据权限定义拦截器 4.15 测试系统相应的功能

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    │ Java面试题49.Struts2的拦截器是什么?你都用它干什么?.mp4 │ Java面试题50.Spring MVC的执行流程.mp4 │ Java面试题51.SpringMVC和Struts2的不同.mp4 │ Java面试题52.简单介绍一下Spring或者Spring的两大核心...

    基于JavaWEB+SSM+mysql框架构建的在线商城系统源码+数据库+项目说明(课程设计).zip

    通过拦截器实现了方法级粒度的鉴权,通过AOP实现了参数校验。 --------------------------- **演示**:[https://small.ડ.com/][1] 可自行注册账号,或使用后台查看权限账号 demo 密码 demo (后台入口登陆后显示...

    asp.net知识库

    正式发布表达式计算引擎WfcExp V0.9(附源码) 运算表达式类的原理及其实现 #实现的18位身份证格式验证算法 身份证15To18 的算法(C#) 一组 正则表达式 静态构造函数 忽略大小写Replace效率瓶颈IndexOf 随机排列算法 ...

Global site tag (gtag.js) - Google Analytics