通过实例解析Spring argNames属性

作者:门罗的魔术师 时间:2023-09-14 10:43:13 

最近学习Spring,一直不太明白Srping的切面编程中的的argNames的含义,经过学习研究后,终于明白,分享一下

需要监控的类:


package bean;
public class HelloApi {
 public void aspectTest(String a,String b){
   System.out.println("in aspectTest:" + "a:" + a + ",b:" + b);
 }
}

类HelloApi的aspectTest方法是需监控的方法,目标是调用前获取获得入参a和b的值,并打印出来。

切面类:


package aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.String;

@Component
@Aspect
public class HelloApiAspect2 {

@Pointcut(value="execution(* bean.HelloApi.aspectTest(..)) && args(a1,b2)",argNames="a1,b2")
 public void pointcut1(String a1,String b2){}

@Before(value="pointcut1(a,b)",argNames="a,b")
 public void beforecase1(String a,String b){
   System.out.println("1 a:" + a +" b:" + b);
 }
 //注意和beforecase1的区别是argNames的顺序交换了
 @Before(value="pointcut1(a,b)",argNames="b,a")
 public void beforecase2(String a,String b){
   System.out.println("2 a:" + a +" b:" + b);
 }
}

测试类:


package UnitTest;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import bean.HelloApi;

public class Test1 {

@Test
 public void aspectjTest1(){
   BeanFactory beanFactory = new ClassPathXmlApplicationContext("chapter2/aspectTest1.xml");
   HelloApi helloapi1 = beanFactory.getBean("helloapi1",HelloApi.class);
   helloapi1.aspectTest("a", "b");
 }
}

Spring的配置文件aspectTest.xml:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:util="http://www.springframework.org/schema/util"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/util
     http://www.springframework.org/schema/util/spring-util-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
 <context:component-scan base-package="aspect"></context:component-scan>

<bean id="helloapi1" class="bean.HelloApi"></bean>
 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

输出:

2 a:b b:a
1 a:a b:b
in aspectTest:a:a,b:b

说明:

HelloApiAspect2定义了一个切面pointcut,切面表达式是execution(* bean.HelloApi.aspectTest(..)) && args(a1,b2),表示配对bean.HelloApi.aspectTest()方法,并且传入参数是2个。

args(a1,b2)另外一个作用,就是定义了aspectTest(String a,String b)方法对应表达式args(a1,b2)。定义了args(a1,b2),才能把目标方法aspectTest的参数传入到切面方法beforecase1的参数中,a参数对应a1,b参数对应b2。使用的方法是按顺序一一对应,aspectTest第一个参数对args第一个参数,aspectTest第2个参数对args第2个参数.

argNames是可选的,如果没有argNames这个参数,而编译器设置了【在class文件生成变量调试信息】,则spring可以通过反射知道方法参数的名字,通过名字配对,Spring知道args(a1,b2)表达式里面的a1和b2,对应了pointcut1(String a1,String b2)方法里面的a1和b2。

目标方法和切入方法的参数的关系是这样确立的:aspectTest(String a,String b) 与 args(a1,b2)关系是a对a1,b对b2(),args(a1,b2)与pointcut1(String a1,String b2)关系是args的a1对pointcut1的a1,args的a2对pointcut1的a2。解决了目标方法参数传入到切入方法参数的问题。

但是,如果设置了argNames,Spring不再使用方法参数的名字来配对,使用argNames定义的顺序来定义pointcut1(String a1,String b2)的顺序,例如:argNames="a1,b2",a1在b2前面,表示pointcut1方法第一个参数是a1,第二个参数是b2。

既然不设置argNames,Spring可以根据参数名字进行配对,为什么还需要配置argNames?因为Spring要知道方法的参数名,编译器必须设置了【在class文件生成变量调试信息】,如果没有设置,Spring就不知道pointcut1方法的参数名了,这个时候,Spring只知道参数的类型,Spring会使用参数的类型进行配对,如果出现2个参数都是同一个类型的情况,就会报AmbiguousBindingException异常。

beforecase1和beforecase2的argNames设置的顺序交换了,调用beforecase1的顺序是beforecase1("a","b"),调用beforecase2的顺序是beforecase2("b","a"),所以最后的输出是

2 a:b b:a
1 a:a b:b

PS:

【class文件中生成变量调试信息】在myeclipse中打开windows-》preferences,设置如下:

通过实例解析Spring argNames属性

来源:https://www.cnblogs.com/powerwu/p/5211611.html

标签:Spring,argNames
0
投稿

猜你喜欢

  • C# SQlite操作方法小结

    2021-10-01 15:56:09
  • 如何把JAR发布到maven中央仓库的几种方法

    2022-11-08 11:07:06
  • IDEA报错:无效的源发行版解决方案

    2022-06-05 08:38:58
  • spring security在分布式项目下的配置方法(案例详解)

    2022-12-26 03:45:49
  • Springboot Websocket Stomp 消息订阅推送

    2022-05-08 14:39:30
  • WPF实现页面的切换的示例代码

    2023-09-26 21:35:27
  • C#实现的XML操作类实例

    2022-04-04 12:17:37
  • Spring boot实现文件上传功能

    2023-08-01 07:00:02
  • Android 自定义输入手机号自动添加分隔符

    2022-08-15 12:32:27
  • Java反射概念与使用实例代码

    2022-02-24 23:55:40
  • java虚拟机中多线程总结

    2022-09-01 22:55:48
  • Java操作文件输出为字符串以及字符串输出为文件的方法

    2022-02-01 19:32:45
  • SpringBoot使用Spark过程详解

    2021-07-30 06:19:21
  • Java代理深入讲解之静态代理

    2022-10-25 14:56:12
  • LZ77压缩算法原理的理解

    2023-01-16 17:48:02
  • Android实现EditText控件禁止输入内容的方法(附测试demo)

    2021-06-26 08:43:38
  • 浅谈Java中ArrayList线程不安全怎么办

    2023-10-02 19:24:56
  • C#验证控件validator的简单使用

    2023-04-26 06:05:31
  • C#检查foreach判读是否为null的方法

    2021-10-28 01:37:24
  • java数据结构与算法之快速排序详解

    2023-02-23 10:23:43
  • asp之家 软件编程 m.aspxhome.com