上一节分析到 invoke方法主要有两行代码
1.获取Interceptor chain
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
2.执行advice的调用
retVal = invocation.proceed(); 执行Interceptor链 这里是一个递归的过程
这里继续分析invocation.proceed()
显示创建一个ReflectiveMethodInvocation对象 然后执行它的proceed方法
org.springframework.aop.framework. ReflectiveMethodInvocation 是AOP联盟的标准接口org.aopalliance.intercept.MethodInvocation的一个实现
public Object proceed() throws Throwable { //currentInterceptorIndex 初始值是-1 每次处理一个Interceptor 就会++ 最后相等的话 就说明Interceptor处理完了 就可以使用 //invokeJoinpoint 调用真实目标对象的方法了 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } //获取一个Interceptor 同时currentInterceptorIndex 会++ Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); //我们的不是InterceptorAndDynamicMethodMatcher 所以都是直接到else的 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { //这里就开始递归了 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
如果是前置通知 就是先执行advice的before方法 然后继续做proceed();递归下去
此时你的前置advice里面的逻辑已经被执行
public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); }
如果是后置通知
就是先进入下一层的proceed(); this.advice.afterReturning( )是先不执行的 等到proceed( )递归到出口了 执行完了以后一层层的返回的时候 this.advice.afterReturning( )才会执行
而递归的出口 就是真实target的方法被调用的时候
public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; }
我们假设已经到了最后一层的proceed()方法 此时Interceptor已经处理完了
那么proceed()方法重 this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1就会为true
于是执行invokeJoinpoint()方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } protected Object invokeJoinpoint() throws Throwable { return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments); }
这个方法在 AopUtils里面了 public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) throws Throwable { // Use reflection to invoke the method. try { ReflectionUtils.makeAccessible(method);//突破修饰符访问限制 return method.invoke(target, args); //最终调用方法返回 } catch (InvocationTargetException ex) { // Invoked method threw a checked exception. // We must rethrow it. The client won't see the interceptor. 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); } }
至此 target的方法也得到了调用
然后proceed( )方法会一层一层的返回 然后后置通知的afterReturning方法也就得到调用
public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; }
这样一来 你的前置通知 后置通知 和 target原始方法 都得到了调用
这里 处理最巧妙的 还是
org.springframework.aop.framework.ReflectiveMethodInvocation 里的 proceed()方法
通过this.currentInterceptorIndex 来控制递归 每处理一个Interceptor 就增加1 等Interceptor处理完毕以后
就结束递归 进入joinpointInvoke()方法 去调用真实的target方法
我们的前置通知是MethodBeforeAdviceInterceptor类的实例 它的invoke方法是先调用advice的before()方法 执行前置通知的代码
然后重新进入proceed方法
我们的后置通知是AfterReturningAdviceInterceptor类的实例 它的invoke方法是调用proceed进入 进入下一层递归 等到递归结束,真实target对象的方法执行完了
返回回来的时候 才执行advice的aterReturning方法 执行后置通知的代码
通过这样一个逻辑 spring很巧妙的实现了在target目标方法调用前 依次执行了前置advice , 在target方法调用之后 依次执行了后置advice
从而实现了AOP的切面关注点的代码织入.
这次分析的是jdk动态代理实现的AOP 而且只分析了前置 后置 ,没有分析异常的advice处理
下次会专门分析一下看ThrowsAdvice的处理
以及cglibAop的处理逻辑
相关推荐
下面是一个简单的示例,演示了如何使用JDK动态代理为一个接口创建代理对象,并在方法调用前后添加日志记录功能。 ```java /** * 业务接口 */ public interface IHello { void hello(String name); } /** * ...
### 关于JDK动态代理的源码剖析 #### 一、引言 在Java开发过程中,动态代理技术是一项非常实用的技术,它可以帮助我们实现在不修改原有代码的基础上为方法增加额外的功能,比如日志记录、权限校验等。本文将深入...
在Java开发中,动态代理和CGLIB代理是两种常见的面向切面编程(AOP)实现方式,它们都用于在不修改原有代码的情况下,增强或扩展对象的功能。本篇文章将深入探讨JDK动态代理和CGLIB代理的区别,以及它们在实际应用中...
在 Spring AOP 框架中,默认情况下,Spring 会选择使用 JDK 动态代理,但是如果目标对象没有实现接口,Spring 就会选择使用 CGLIB 动态代理。这种机制可以确保 Spring AOP 框架可以代理任何类型的对象,无论它是否...
在Java编程领域,JDK动态代理是一个非常重要的概念,它允许我们在运行时动态地创建一个实现了特定接口的代理对象,以此来拦截并扩展原有对象的行为。动态代理在很多场景下都有应用,比如AOP(面向切面编程)、事件...
动态代理的优点在于可以在不修改原有代码的情况下,增加新的功能,从而提高软件的灵活性和扩展性。 结论 JDK 动态代理技术是 Java 语言自身对动态代理的支持,提供了一种灵活和高效的方式来实现动态代理。通过...
总之,JDK动态代理为我们提供了一种灵活的代码扩展机制,使得在不修改原有代码的情况下,可以方便地添加额外的功能或者监控代码行为。在实际项目中,如日志记录、性能监控、事务管理等方面,JDK动态代理都有广泛的...
在Java编程领域,JDK动态代理是实现动态创建代理对象的一种技术,它是Java标准库提供的一种强大工具。Spring AOP(面向切面编程)则是一种流行的应用框架,它利用动态代理来实现对业务代码的切面增强,如日志、事务...
Java代理机制为我们提供了在运行时扩展功能的能力,无论是JDK动态代理还是CGLIB代理,都是为了在不修改源代码的前提下,增加新的行为或者监控已有行为。选择哪种代理方式取决于具体需求,如果目标类实现了接口,优先...
Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...
2. **Callback接口**:类似于JDK动态代理的`InvocationHandler`,CGlib使用`Callback`接口来处理方法调用。常见的`Callback`实现有`MethodInterceptor`,它允许我们在方法调用前后插入自定义逻辑。 3. **ASM库**:...
- **CGLIB代理**适用于目标类没有接口或者不希望修改原有接口的情况,其性能通常优于JDK代理,因为它是基于字节码生成的子类,而JDK代理需要反射调用接口方法。 在实际开发中,如Spring AOP框架就同时支持JDK和...
- 分析JDK动态代理的源码,可以了解其内部如何生成代理类和调用处理程序的工作机制。 - Spring AOP的源码解析有助于理解其是如何创建代理、匹配切点并执行相应通知的过程。 5. **工具应用**: - JDK动态代理和...
这个代理对象实现了目标对象的所有接口,因此可以在不修改原有代码的情况下,对方法调用进行拦截。当我们通过代理调用方法时,实际上是在调用`InvocationHandler`的`invoke`方法。 `InvocationHandler`接口有一个`...
在Java编程中,动态代理是一种强大的技术,...通过阅读和分析提供的代码文件(3-1代码、3-2代码、3-3代码),我们可以看到具体的实现细节,如方法的调用链路、参数处理和异常处理等,从而进一步巩固对动态代理的理解。
jdk 的动态代理和CGLIB代理
总结,Java JDK的动态代理为我们提供了一种灵活的方式,可以在不修改原始代码的情况下扩展或修改对象的行为。通过创建代理对象,我们可以方便地实现如日志记录、事务管理、权限验证等附加功能,极大地提高了代码的可...
总结起来,JDK动态代理适用于目标对象实现了接口的情况,而CGLIB代理则可以在没有接口的情况下进行代理。两者都可以实现运行时的代理,但适用场景不同,开发者可以根据具体需求选择适合的代理方式。在实际开发中,...
这个过程展示了动态代理如何帮助我们在不修改原始业务代码的情况下,增加日志记录功能。这种机制对于开发灵活、可扩展的应用程序非常有用,尤其是在需要实现横切关注点的场景下。 #### 五、动态代理的局限性与扩展 ...