关于 Spring AOP 中,包含参数的成员方法的调用,出现 NoSuchMethodException 的研究

原创 2017年01月02日 21:22:57

关于 Spring AOP 中,包含参数的成员方法的调用,出现 NoSuchMethodException 的研究


网上看了一大堆,大都是关于init方法和构造方法的情况,可能此处有些特殊。

发出来交流一下。


Spring版本 - spring-framework-2.5.6-with-dependencies

在使用中,偶然用到一个单独的有参数的方法的调用,包了错误
NoSuchMethodException

首先不是修饰符的问题 - 因为内部有暴力访问机制
源码 ——


package org.springframework.util;

public abstract class ReflectionUtils 

/**
 * Make the given method accessible, explicitly setting it accessible if necessary.
 * The <code>setAccessible(true)</code> method is only called when actually necessary,
 * to avoid unnecessary conflicts with a JVM SecurityManager (if active).
 * @param method the method to make accessible
 * @see java.lang.reflect.Method#setAccessible
 */
public static void makeAccessible(Method method) {
    if (!Modifier.isPublic(method.getModifiers()) ||
            !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
        method.setAccessible(true);
    }
}

在Spring的AOP中会自动完成方法的切入点表达式的匹配

mi  Cglib2AopProxy$CglibMethodInvocation  (id=131) 

org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(insert)

相关的关键生成类


package org.springframework.aop.aspectj;

public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor

/**
 * Return the ProceedingJoinPoint for the current invocation,
 * instantiating it lazily if it hasn't been bound to the thread already.
 * @param rmi the current Spring AOP ReflectiveMethodInvocation,
 * which we'll use for attribute binding
 * @return the ProceedingJoinPoint to make available to advice methods
 */
protected ProceedingJoinPoint lazyGetProceedingJoinPoint(ProxyMethodInvocation rmi) {
    return new MethodInvocationProceedingJoinPoint(rmi);
}

org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(insert)

后期会在此处使用


protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
        [org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(insert)]
    Object[] actualArgs = args;
    if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
        actualArgs = null;
    }
    try {
        ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
        // TODO AopUtils.invokeJoinpointUsingReflection
        return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
    }
    catch (IllegalArgumentException ex) {
        throw new AopInvocationException("Mismatch on arguments to advice method [" +
                this.aspectJAdviceMethod + "]; pointcut expression [" +
                this.pointcut.getPointcutExpression() + "]", ex);
    }
    catch (InvocationTargetException ex) {
        java.lang.reflect.InvocationTargetException
        throw ex.getTargetException();
    }
}

最终可能出现报错的产出位置


package org.springframework.aop.aspectj;

public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor 

public Object invoke(MethodInvocation mi) throws Throwable {
    if (!(mi instanceof ProxyMethodInvocation)) {
        throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
    }
    ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
    ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
    return invokeAdviceMethod(pjp, jpm, null, null);
}

重点看pmi 与pjp

解决办法 -

由于这种机制的存在,主要是引起通知方法的调用和匹配

在其内部,获取有参方法会先匹配切入点
而切入点的自动生成机制比较简单
例如

本应该是
...insert(java.lang.String); target is of class ...

结果生成的切入点表达式为
org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution(insert)

那么,在此处,无参的方法为了使用是必须出现的

但是如果本身并不需要调用的话,那么就没有什么意义

如同AOP的注解中定义的切入点表达式一般,并无任何意义,方法体不调用,是不会执行的。
只是避免了内部机制实现的报错而已。

由于当前项目配置较为驳杂,后期有空单独把这一部分抽取出来进行测试研究,如有更好的见解,欢迎评论交流。

如需要转载
请注明文章出处
http://blog.csdn.net/muxingye/article/details/53982313
谢谢~

版权声明:本文为博主原创文章,未经博主允许不得转载。

Spring中AOP的几个概念

面向切面编程提供了另外一种角度来思考程序结构,通过这种方式来弥补面向对象(OOP)的不足。除了classes(类)以外,AOP提供了切面!切面对关注点进行模块化,例如横切多个类型和对象的事物管理。这个...
  • zh23862691
  • zh23862691
  • 2013年09月20日 20:30
  • 2076

spring的aop拦截action中的方法会报java.lang.NoSuchMethodException: $Proxy97.test()异常

知识点1: proxy-target-class 属性值决定bean是基于jdk的接口方式的还是基于类的代理(CGLIB)被创建。 在ssh整合的项目中如果action继承了实现了别的接口的类,...
  • u014087707
  • u014087707
  • 2016年02月04日 10:20
  • 383

Spring学习笔记四(AOP中的通知参数和注解开发)

1.前言 上一篇博客介绍了如何通过AOP来切入我们想实现的公共性的功能,这篇博客来讲一下,当我们拦截到方法后,如何来获取通知参数。这也是AOP的精髓所在,通过AOP可以实现偷梁换柱的功能。我们把原来...
  • ZHOUCHAOQIANG
  • ZHOUCHAOQIANG
  • 2015年08月11日 15:46
  • 4927

SpringAOP 处理通知中的参数(注解与xml配置)

上一篇文章讲的是springaop的最基本配置,没有任何参数,有参数的也就在环绕通知@Around 中使用了ProceedingJoinPoint 作为参数,要是切面所通知的方法确实有参数该怎么办?下...
  • qqHJQS
  • qqHJQS
  • 2016年11月29日 23:53
  • 2575

Java精选笔记_面向对象(构造方法、this关键字、static关键字、内部类)

构造方法constructor构造器 构造方法的定义 [修饰符]  类名 (形式参数列表){         //语句 } 构造器用于构造该类的实例。作用:用来初始化对象!一般由系统在创建对...
  • xiaoye142034
  • xiaoye142034
  • 2017年06月28日 01:21
  • 192

Spring AOP不拦截从对象内部调用的方法原因

拦截器的实现原理很简单,就是动态代理,实现AOP机制。当外部调用被拦截bean的拦截方法时,可以选择在拦截之前或者之后等条件执行拦截方法之外的逻辑,比如特殊权限验证,参数修正等操作。   但是最近在...
  • TianDiYiShaOu_
  • TianDiYiShaOu_
  • 2016年04月21日 10:10
  • 1454

springAOP报java.lang.NoSuchMethodException: $Proxy和使用AOP后action采用autoware注入值为null

在使用spring的annotation注解通过AOP在action上进行log记录时,产生了java.lang.NoSuchMethodException: $Proxy的错误,这是由于配置不完全产...
  • luosheng1125
  • luosheng1125
  • 2013年07月11日 14:04
  • 1655

Spring中IOC与AOP的理解

关于IOC我们知道是Spring中很重要的组合部分,下面就IOC的理解写一点自己的心得: 1.IOC是什么? IOC也称控制反转,其实是和依赖注入的含义是一样的,就是把原先控制代码对象的生产由代码...
  • qq_35347459
  • qq_35347459
  • 2017年04月26日 17:51
  • 576

Spring AOP无法拦截对象的内部方法调用问题

参考: http://fyting.iteye.com/blog/109236
  • luojinbai
  • luojinbai
  • 2017年01月19日 08:20
  • 1149

Spring AOP(六)之访问目标方法的参数

访问目标方法最简单的做法是定义增强处理方法时将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强的连接点。JoinPOINT里包含了如下几个常用...
  • owen_william
  • owen_william
  • 2016年03月06日 12:30
  • 1236
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于 Spring AOP 中,包含参数的成员方法的调用,出现 NoSuchMethodException 的研究
举报原因:
原因补充:

(最多只允许输入30个字)