Spring AOP深入理解之拦截器调用
2015-06-30 14:41
597 查看
Spring AOP深入理解之拦截器调用
Spring AOP代理对象生成回顾
上一篇博客中:深入理解Spring AOP之二代理对象生成介绍了Spring代理对象是如何生成的,其中重点介绍了JDK动态代理方式,简单回顾下代理对象生成过程:1、上面讲到了两种生成代理对象的方法,一种是通过ProxyFactory,一种是通过ProxyFactoryBean。第一种获取比较简单,但是需要手工的进行写代码,而第二种是通过Spring的IOC机制来控制Bean的生成。2、无论是ProxyFactory或者ProxyFactoryBean都是要通过createAopProxy().getProxy()来获取相应的代理对象,而通过Proxyfactory比较直接,上面重点介绍的是通过ProxyFactoryBean获得proxy。
3、首先,找到ProxyFactoryBean的getObject方法,为什么?(主要是跟Bean容器中getObject能返回代理对象)
4、其次调用getSingletonInstance(),在getSingletonInstance方法中引入了super中的方法,super是指ProxyCreatorSupport,这里ProxyCreatorSupport是ProxyFactoryBean和ProxyFactory的父类,已经做了很多工作,只需在ProxyFactoryBean的getObject()方法中通过父类的createAopProxy()取得相应的AopProxy。
5、跟踪createAopProxy方法,追踪到了ProxyCreatorSupport中,然后,借助了AopProxyFactory,此时得到的aopProxyFactory,在构造函数中已经定义为DefaultAopProxyFactory
6、进入DefaultAopProxyFactory中,找到createAopProxy方法,在这里判断是调用JDK动态或者CGlib动态中的一种。
既然代理对象已经生成,那么拦截器是如何被调用的呢
回顾下JdkDynamicAopProxy中生成proxy方法@Override public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }看最后一句return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)。这个地方的三个参数在博客动态代理中做过详细介绍,再回顾下classloader类加载器,定义了由哪个ClassLoader对象来对生成的代理对象进行加载proxiedInterfaces,一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口this,表示JdkDynamicAopProxy自身,因为JdkDynamicAopProxy实现了InvocationHandler接口在动态代理这篇博客中我们分析过,生成的proxy代理类被调用时,会调用super.h.method()方法,这里的super一般指的是Proxy,而Proxy中有一个InvocationHandler,即h。所以InvocationHandler的invoke方法会被作为回调函数调用
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { //目标对象未实现equals方法 return equals(args[0]); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { //目标对象未实现hashcode方法 return hashCode(); } if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { //这里就是目标对象方法的调用 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { // 获得当前的对象 oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //目标对象可能源自一个池或者一个简单的方法 target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // 得到拦截器链 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // 检查是否定义了拦截器方法,如果没有的话直接调用目标方法 if (chain.isEmpty()) { retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { //我们需要创建一个调用方法 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // proceed内部实现了递归调用遍历拦截器链 retVal = invocation.proceed(); } Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // 释放target对象 targetSource.releaseTarget(target); } if (setProxyContext) { // 替换回原来的proxy AopContext.setCurrentProxy(oldProxy); } } }
上面的invoke()主要分为三部分
拦截器链的获取, this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)目标对象方法的调用,即invokeJoinpointUsingReflection()方法拦截器对象方法的调用,即ReflectiveMethodInvocation中proceed()
首先看拦截器链是如获得的。
进入AdvisedSupport(advised为AdvisedSupport实例)的getInterceptorsAndDynamicInterceptionAdvice()方法public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, 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; }可以看出上面方法用到缓存的, 假设现在缓存没有相应的拦截器, 则到 AdvisorChainFactory 的相应方法中获取,继续跟踪AdvisorChainFactory,发现定义为new DefaultAdvisorChainFactory(),这里是不是有一点眼熟,对的,在上一篇中讲到动态代理是也有一个DefaultAopProxy,进入DefaultAdvisorChainFactory中的相应方法,比较长
/** * 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor, * 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断 * 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回. */
public List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Methodmethod, Class targetClass) { List interceptorList = new ArrayList(config.getAdvisors().length); //查看是否包含IntroductionAdvisor boolean hasIntroductions = hasMatchingIntroductions(config,targetClass); //这里实际上注册一系列AdvisorAdapter,用于将Advisor转化成MethodInterceptor AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); Advisor[] advisors = config.getAdvisors(); for (int i = 0; i <advisors.length; i++) { Advisor advisor = advisors[i]; if (advisor instanceof PointcutAdvisor) { // Add it conditionally. PointcutAdvisor pointcutAdvisor= (PointcutAdvisor) advisor; if(config.isPreFiltered() ||pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) { //TODO: 这个地方这两个方法的位置可以互换下 //将Advisor转化成Interceptor MethodInterceptor[]interceptors = registry.getInterceptors(advisor); //检查当前advisor的pointcut是否可以匹配当前方法 MethodMatcher mm =pointcutAdvisor.getPointcut().getMethodMatcher(); if (MethodMatchers.matches(mm,method, targetClass, hasIntroductions)) { if(mm.isRuntime()) { // Creating a newobject instance in the getInterceptors() method // isn't a problemas we normally cache created chains. for (intj = 0; j < interceptors.length; j++) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptors[j],mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } else if (advisor instanceof IntroductionAdvisor){ IntroductionAdvisor ia =(IntroductionAdvisor) advisor; if(config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) { Interceptor[] interceptors= registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { Interceptor[] interceptors =registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; }注意上面代码中的一行,注册一系列AdvisorAdapter,找到GlobalAdvisorAdapterRegistry,其实定义为 new DefaultAdvisorAdapterRegistry(),又是default~~~
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); instance = new DefaultAdvisorAdapterRegistry(); public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); }所以registry其实为调用了DefaultAdvisorAdapterRegistry的构造函数,然后才能在将Advisor转化成Interceptor时,调用DefaultAdvisorAdapterRegistry的getInterceptors()方法。
@Override public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return interceptors.toArray(new MethodInterceptor[interceptors.size()]); }这里的MethodInterceptor[]返回值,正好可以匹配上面代码中的 MethodInterceptor[]interceptors = registry.getInterceptors(advisor);
目标对象方法的调用
来看看invokeJoinpointUsingReflection(),即上面所说的目标对象方法的调用,其实是通过AopUtils的方法调用,使用反射机制来对目标对象的方法进行的:public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) throws Throwable { // 通过反射机制来获得相应的方法,并调用invoke try { ReflectionUtils.makeAccessible(method); return method.invoke(target, args); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } catch (IllegalArgumentException ex) { throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", ex); } catch (IllegalAccessException ex) { throw new AopInvocationException("Could not access method [" + method + "]", ex); } }
拦截器方法执行
看看拦截器对象,即ReflectiveMethodInvocation中proceed()方法的调用invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); retVal = invocation.proceed();invocation是一个new ReflectiveMethodInvocation()实例,找到ReflectiveMethodInvocation的proceed()方法
private int currentInterceptorIndex = -1; @Override public Object proceed() throws Throwable { // currentInterceptorIndex初始化的长度为-1,下面就就是判断 //interceptorsAndDynamicMethodMatchers长度是否为0 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { //匹配是否为正确的方法逻辑,(MethodMatcher)可以看出为匹配如果不是就调用下一个 InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { //匹配失败,跳过这个拦截器,继续下一个 return proceed(); } } else { // 如果是interceptor,则调用invoke方法,这是为了兼容 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
相关文章推荐
- Spring4 SpringMVC Hibernate4 Freemaker 集成示例
- java回车登陆
- java迭代器(Iterator)简单使用
- java中String的常用方法
- Java EE应用的组件
- struts2.1笔记07:Sturts.xml配置中的包介绍
- java验证码识别带源码以及讲解视频
- Eclipse中<uses-permission>和<permission>和<uses-feature>区别
- eclipse failed to create the java virtual machine 问题
- java Volatile关键字解析
- 异常 java.lang.UnsatisfiedLinkError,so库没有加载
- java动态爬虫jsoup以及正则表达式的运用
- Java 对象复制
- Java EE应用的分层模型
- struts2 文件上传下载(单文件上传与多文件上传的比较)
- java☞自增自减运算符(++)(--)
- Java 图片添加水印
- java读取properties配置文件
- 【Java Swing探索之路系列】之四:Java Swing用户界面组件(一)
- Java 接口和抽象类区别