Spring源代码解析(七):Spring AOP中对拦截器调用的实现

前面我们分析了Spring AOP实现中得到Proxy对象的过程,下面我们看看在Spring AOP 中拦截器链是怎样被调用的,也就是Proxy模式是怎样起作用的,或者说Spring是怎样为 我们提供AOP功能的;

在JdkDynamicAopProxy中生成Proxy对象的时候:

Java代码

return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

这里的this参数对应的是InvocationHandler对象,这里我们的JdkDynamicAopProxy实 现了这个接口,也就是说当Proxy对象的函数被调用的时候,这个InvocationHandler的 invoke方法会被作为回调函数调用,下面我们看看这个方法的实现:

Java代码

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     MethodInvocation invocation = null;
     Object oldProxy = null;
     boolean setProxyContext = false;
     TargetSource targetSource = this.advised.targetSource;
     Class targetClass = null;
     Object target = null;
     try {
       // Try special rules for equals() method and implementation of the
       // Advised AOP configuration interface.
       if (!this.equalsDefined && AopUtils.isEqualsMethod (method)) {
         // What if equals throws exception!?
         // This class implements the equals(Object) method itself.
         return equals(args[0]) ? Boolean.TRUE : Boolean.FALSE;
       }
       if (!this.hashCodeDefined && AopUtils.isHashCodeMethod (method)) {
         // This class implements the hashCode() method itself.
         return new Integer(hashCode());
       }
       if (Advised.class == method.getDeclaringClass()) {
         // service invocations on ProxyConfig with the proxy config
         return AopUtils.invokeJoinpointUsingReflection (this.advised, method, args);
       }
       Object retVal = null;
       if (this.advised.exposeProxy) {
         // make invocation available if necessary
         oldProxy = AopContext.setCurrentProxy(proxy);
         setProxyContext = true;
       }
       // May be <code>null</code>. Get as late as possible to minimize the time we "own" the target,
       // in case it comes from a pool.
       // 这里是得到目标对象的地方,当然这个目标对象可能来自于一个实例 池或者是一个简单的JAVA对象
       target = targetSource.getTarget();
       if (target != null) {
         targetClass = target.getClass();
       }
       // get the interception chain for this method
       // 这里获得定义好的拦截器链
       List chain = this.advised.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice (
           this.advised, proxy, method, targetClass);
       // Check whether we have any advice. If we don't, we can fallback on direct
       // reflective invocation of the target, and avoid creating a MethodInvocation.
       // 如果没有设定拦截器,那么我们就直接调用目标的对应方法
       if (chain.isEmpty()) {
         // We can skip creating a MethodInvocation: just invoke the target directly
         // Note that the final invoker must be an InvokerInterceptor so we know it does
         // nothing but a reflective operation on the target, and no hot swapping or fancy proxying
         retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
       }
       else {
         // We need to create a method invocation...
         // invocation = advised.getMethodInvocationFactory ().getMethodInvocation(
         //     proxy, method, targetClass, target, args, chain, advised);
         // 如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象 的相应方法
         // 这里通过构造一个ReflectiveMethodInvocation来实现,下面我 们会看这个ReflectiveMethodInvocation类
         invocation = new ReflectiveMethodInvocation(
             proxy, target, method, args, targetClass, chain);
         // proceed to the joinpoint through the interceptor chain
         // 这里通过ReflectiveMethodInvocation来调用拦截器链和相应的 目标方法
         retVal = invocation.proceed();
       }
       // massage return value if necessary
       if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy)) {
         // Special case: it returned "this" and the return type of the method is type-compatible
         // Note that we can't help if the target sets
         // a reference to itself in another returned object.
         retVal = proxy;
       }
       return retVal;
     }
     finally {
       if (target != null && !targetSource.isStatic()) {
         // must have come from TargetSource
         targetSource.releaseTarget(target);
       }
       if (setProxyContext) {
         // restore old proxy
         AopContext.setCurrentProxy(oldProxy);
       }
     }
   }

时间: 2024-08-02 20:55:08

Spring源代码解析(七):Spring AOP中对拦截器调用的实现的相关文章

struts2整合spring3后,指定spring管理action之后,配置的struts2的拦截器,拦截不到东西

问题描述 struts2整合spring3后,指定spring管理action之后,配置的struts2的拦截器,拦截不到东西 struts2整合spring3后,指定spring管理action之后,配置的struts2的拦截器,拦截不到东西,这是什么原因??? Struts2的Action可以交给Spring管理,但Struts2的拦截器就拦截到不到请求了,望高手帮忙! 解决方案 我也遇到同样的问题 不整合的时候struts什么都能拦,整合后就拦不了了

JavaWeb中Struts2拦截器深入分析(一)_java

一.struts2中的拦截器(框架功能核心) 1.过滤器VS拦截器 过滤器VS拦截器功能是一回事.过滤器是Servlet规范中的技术,可以对请求和响应进行过滤. 拦截器是Struts2框架中的技术,实现AOP(面向切面)的编程思想,是可插拔的, 可以对访问某个 Action 方法之前或之后实施拦截. 拦截器栈(Interceptor Stack): 将拦截器按一定的顺序联结成一条链. 在访问被拦截的方法时, Struts2拦截器链中的拦截器就会按其之前定义的顺序被依次调用 Struts2执行原理

Springnvc框架中的拦截器如何配置可以拦截html页面的请求?

问题描述 Springnvc框架中的拦截器如何配置可以拦截html页面的请求? Springnvc框架中的拦截器如何配置可以拦截html页面的请求? 解决方案 SpringMVC及拦截器基本配置:http://se7en8974.iteye.com/blog/826670 springMVC 拦截器简单配置:http://blog.csdn.net/lqx1988221/article/details/36420887

JavaWeb开发中alias拦截器的使用方法_java

在SSH项目中,有时需要由一个Action跳转到另一个Action.有两种方式可以实现Action之间的跳转,一种是chain,另一种是redirectAction,这两种方式之间的区别是chain是在服务器上跳转,可以实现不同Action之间的数据共享:而redirectAction是在客户端进行跳转. 使用chain在不同的Action之间传递参数值,这个功能可以通过alias拦截器来实现. 1. 指定Filter类 在web.xml中设置下面的拦截器: <filter> <filt

Spring源代码解析(五):Spring AOP获取Proxy

下面我们来看看Spring的AOP的一些相关代码是怎么得到Proxy的,让我们我们先看看 AOP和Spring AOP的一些基本概念: Advice: 通知,制定在连接点做什么,在Sping中,他主要描述Spring围绕方法调用注入的额外 的行为,Spring提供的通知类型有: before advice,AfterReturningAdvice,ThrowAdvice,MethodBeforeAdvice,这些都是 Spring AOP定义的接口类,具体的动作实现需要用户程序来完成. Poin

Spring源代码解析(六):Spring声明式事务处理

我们看看Spring中的事务处理的代码,使用Spring管理事务有声明式和编程式两种方 式,声明式事务处理通过AOP的实现把事物管理代码作为方面封装来横向插入到业务代码 中,使得事务管理代码和业务代码解藕.在这种方式我们结合IoC容器和Spirng已有的 FactoryBean来对事务管理进行属性配置,比如传播行为,隔离级别等.其中最简单的方 式就是通过配置TransactionProxyFactoryBean来实现声明式事物: 在整个源代码分析中,我们可以大致可以看到Spring实现声明式事物

Spring源代码解析(三):Spring JDBC

下面我们看看Spring JDBC相关的实现, 在Spring中,JdbcTemplate是经常被使用的类来帮助用户程序操作数据库,在 JdbcTemplate为用户程序提供了许多便利的数据库操作方法,比如查询,更新等,而且在 Spring中,有许多类似 JdbcTemplate的模板,比如HibernateTemplate等等 - 看来这是 Rod.Johnson的惯用手法,一般而言这种Template中都是通过回调函数CallBack类的使用 来完成功能的,客户需要在回调接口中实现自己需要的

Spring源代码解析(十):Spring Acegi框架授权的实现

我们从FilterSecurityInterceptor我们从入手看看怎样进行授权的: Java代码 //这里是拦截器拦截HTTP请求的入口 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request

如何在基于注解风格的Spring-MVC中使用拦截器

Spring-MVC如何使用拦截器,官方文档只给出了非注解风格的例子.那么基于注解风格如何使用拦截器呢? 基于注解基本上有2个可使用的定义类,分别是DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter: <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> <be