SpringAOP切入点规范及获取方法参数的实现

切入点规范

@Pointcut("execution(* com.example.server.service.TeacherService.*(..))")

上面的切入点会切入com.example.server.service.TeacherService下面的所有方法。

下面来详细介绍一下切入点表达式的规范。

1、execution():表达式主体。

2、第一个位置:表示返回类型, *号表示所有的类型。

3、第二个位置:表示需要拦截的包名.类名.方法名(方法参数)。

需要注意的是必须是全类名。其中可以使用*表示所有包。

比如说:com.example.server.service.表示service包下的所有类;com.example.server..则表示server包下的所有包及其所有类。

可以具体指定某一个方法,也可以用表示该类的所有方法(满足之前的返回类型)

同样,参数可以是具体的,例如:(int, String),也可以用(..)来表示任意参数。(只有参数匹配的方法才能被切入)

AOP中获取方法参数

"execution(* com.example.server.service.TeacherService.uploadExperience(..)) && args(userId)"

大家可以看到,在以上表达式的基础上添加了一点改动,这样我们就能在AOP中获取到切入方法调用时的参数,这样我们就能在AOP方法中使用这个参数。

以下是一个示例:

    @After("execution(* com.example.server.service.TeacherService.uploadExperience(..)) && args(userId)")
    public void updateLevel(Long userId){
  //代码块,现在就可以在代码块中使用userId
    }

AOP获取session的参数

有时需要在AOP中使用到之前存储在session中的值。其实这也非常简单。

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession session = attr.getRequest().getSession(true);
long userId = (long) session.getAttribute(USER_ID);

同理,我们通过ServletRequestAttributes也可以获取到request和response

HttpServletResponse response = attr.getResponse();
HttpServletRequest request = attr.getRequest();

SpringAOP:获取切入点注释的参数

spring aop如何在切面类中获取切入点相关方法的参数、方法名、返回值、异常等信息

aop思想可以很好的帮助我们实现代码的解耦,比如我们之前提到的,将日志代码与业务层代码完全独立,通过spring aop的代理类进行整合。在切面类中,我们也能够通过spring提供的接口,很好的获取原切入点的相关信息。

首先,我们还是从代码着手

业务层代码StudentServiceImpl

@Service("studentService")
public class StudentServiceImpl implements StudentService {
    @Override
    public int addStudent(Student student) throws Exception {
            System.out.println("addStudent...业务层代码执行...");
            return 1;
    }
    @Override
    public int deleteStudent(Integer id) throws Exception{
            System.out.println("deleteStudent...业务层代码执行...");
            int i = 1/0;
            return 0;
    }
}

切面类StudentServiceLogger

@Aspect
@Component
public class StudentServiceLogger {
    @Before("execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )")
    public void doBefore(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        String methodName = joinPoint.getSignature().getName();
        System.out.println(methodName+"方法执行前...");
        System.out.println("参数为:"+ Arrays.asList(args));
    }

    @After("execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )")
    public void doAfter(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println(methodName+"方法执行后...");
    }

    @AfterReturning(value = "execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )" , returning = "returning")
    public void doReturn(JoinPoint joinPoint,Object returning){
        String methodName = joinPoint.getSignature().getName();
        System.out.println(methodName+"方法返回,返回值为:"+returning);
    }

    @AfterThrowing(value = "execution(* com.wuwl.service.impl.StudentServiceImpl.*(..) )",throwing = "ex")
    public void doThrow(JoinPoint joinPoint,Exception ex){
        String methodName = joinPoint.getSignature().getName();
        System.out.println(methodName+"方法异常,异常信息为:"+ex.getMessage());
    }
}

测试类AopTest

public class AopTest {
    ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    @Test
    public void test1() throws Exception {
        StudentService studentService = ac.getBean("studentService",StudentService.class);
        studentService.addStudent(new Student());
        System.out.println("==================割===============");
        studentService.deleteStudent(1);
    }
}

最后是日志输出结果

addStudent方法执行前...
参数为:[com.wuwl.domain.Student@7e5c856f]
addStudent...业务层代码执行...
addStudent方法执行后...
addStudent方法返回,返回值为:1
==================割===============
deleteStudent方法执行前...
参数为:[1]
deleteStudent...业务层代码执行...
deleteStudent方法执行后...
deleteStudent方法异常,异常信息为:/ by zero

关于切入点方法的相关信息,spring很好的封装在了org.aspectj.lang.JoinPoint接口中,这里需要注意的是,在org.aopalliance.intercept包下,也有这样命名的一个接口,千万不要搞错了。

joinPoint.getArgs()方法可以返回切入方法的参数信息,返回值为一个数组,遍历即可获取;joinPoint.getSignature()方法的返回值为方法签名,签名接口中就包括方法名之类的信息。

如果需要在通知方法中获取切入方法的返回值,或者异常信息,则需要使用到对应注解的对应属性才行。

点开@AfterReturning注解可以看到一个String returning() default "";属性,在通知方法中添加返回值参数,然后再注解中声明该参数为切入方法的返回值即可,操作方法可参考上面的代码。

同理可以,使用@AfterThrowing注解的String throwing() default "";属性,可以获取到切入方法抛出的异常信息。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringAOP 如何通过JoinPoint获取参数名和值

    SpringAOP 通过JoinPoint获取参数名和值 在Java8之前,代码编译为class文件后,方法参数的类型固定,但是方法名称会丢失,方法名称会变成arg0.arg1-..在Java8开始可以在class文件中保留参数名. public void tet(JoinPoint joinPoint) { // 下面两个数组中,参数值和参数名的个数和位置是一一对应的. Object[] args = joinPoint.getArgs(); // 参数值 String[] argNames

  • SpringAop实现操作日志记录

    前言 大家好,这里是经典鸡翅,今天给大家带来一篇基于SpringAop实现的操作日志记录的解决的方案.大家可能会说,切,操作日志记录这么简单的东西,老生常谈了.不! 网上的操作日志一般就是记录操作人,操作的描述,ip等.好一点的增加了修改的数据和执行时间.那么!我这篇有什么不同呢!今天这种不仅可以记录上方所说的一切,还增加记录了操作前的数据,错误的信息,堆栈信息等.正文开始~~~~~ 思路介绍 记录操作日志的操作前数据是需要思考的重点.我们以修改场景来作为探讨.当我们要完全记录数据的流向的时候,

  • SpringAOP 构造注入的实现步骤

    AOP_面向切面编程初步了解 让我们先想象一个场景,你正在编写一个项目,在开发过程中的多个模块都有某段重复的代码,于是你选择将其抽象成一个方法,然后在需要的地方调用这个方法,当需要修改这段代码时只需要修改这个方法就行.有一天,你的Boss给了新的需求,需要再抽象出一个方法,然后再在各个需要这个方法的模块调用这个方法,这可能就让你头疼了,需要修改大量的代码,于是会想,能不能不修改源代码为系统业务添加某种功能呢?幸运的是,AOP可以很好的解决这个问题. 简单介绍 AOP:保证开发者不修改源代码的前提

  • SpringAOP 设置注入的实现步骤

    AOP_面向切面编程初步了解 让我们先想象一个场景,你正在编写一个项目,在开发过程中的多个模块都有某段重复的代码,于是你选择将其抽象成一个方法,然后在需要的地方调用这个方法,当需要修改这段代码时只需要修改这个方法就行.有一天,你的Boss给了新的需求,需要再抽象出一个方法,然后再在各个需要这个方法的模块调用这个方法,这可能就让你头疼了,需要修改大量的代码,于是会想,能不能不修改源代码为系统业务添加某种功能呢?幸运的是,AOP可以很好的解决这个问题. 简单介绍 AOP:保证开发者不修改源代码的前提

  • springAop实现权限管理数据校验操作日志的场景分析

    前言 作为一个写java的使用最多的轻量级框架莫过于spring,不管是老项目用到的springmvc,还是现在流行的springboot,都离不开spring的一些操作,我在面试的时候问的最多的spring的问题就是我们在平常的项目中使用spring最多的有哪几个点 在我看来无非就两个 spring的bean管理,说的高大上一点就是spring的ioc,di spring的AOP spring是一个很强大的轻量级框架,功能远不止这两点,但是我们用的最多的就是这两点. spring bean 管

  • springAOP中用joinpoint获取切入点方法的参数操作

    springAOP joinpoint获取切入点方法的参数 概念: 访问目标方法即用jointpoint(@around用poceedingjointpoint) 1.获取他们的目标对象信息, 如test.component@80387a这种 2.还有获取带参方法的参数, 如[Ljava.lang.Object;@183cfe9(想当然我们也可以用对象的arrays.toString()方法将其还原) 3.另外还有获取被增强的方法相关信息 如String test.component.test1

  • 自定义注解和springAOP捕获Service层异常,并处理自定义异常操作

    一 自定义异常 /** * 自定义参数为null异常 */ public class NoParamsException extends Exception { //用详细信息指定一个异常 public NoParamsException(String message){ super(message); } //用指定的详细信息和原因构造一个新的异常 public NoParamsException(String message, Throwable cause){ super(message,

  • SpringAOP切入点规范及获取方法参数的实现

    切入点规范 @Pointcut("execution(* com.example.server.service.TeacherService.*(..))") 上面的切入点会切入com.example.server.service.TeacherService下面的所有方法. 下面来详细介绍一下切入点表达式的规范. 1.execution():表达式主体. 2.第一个位置:表示返回类型, *号表示所有的类型. 3.第二个位置:表示需要拦截的包名.类名.方法名(方法参数). 需要注意的是

  • SpringAOP如何获取方法参数上的注解

    SpringAOP获取方法参数上的注解 一.示例 ① 如下代码,自定义一个参数注解@Test,并将其使用到方法参数上,用于标注需要检验的参数 /** * 自定义注解,用于参数 */ @Target(PARAMETER) @Documented @Retention(RetentionPolicy.RUNTIME) public @interface Test{ } /** * 接口层,使用使用@Test注解标记参数 */ @RestController @RequestMapping("/v1/

  • 使用spring通过aop获取方法参数和参数值

    目录 spring通过aop获取方法参数和参数值 自定义注解 切面 aop切面 注解.参数获取 1.定义需要切面的注解 2.在需要进行切面的方法标注注解 3.定义切面 spring通过aop获取方法参数和参数值 自定义注解 package com.xiaolc.aspect; import java.lang.annotation.*; /** * @author lc * @date 2019/9/10 */ @Documented @Target({ElementType.TYPE, Ele

  • 聊聊在获取方法参数名方面,Spring真的就比Mybatis强?

    目录 前言 一.Spring是如何获取方法参数名称的? Spring获取参数名称的两种方式 二.Mybatis为什么没有向Spring学习? Mybatis要获取的是接口方法的参数名称 三.总结 四.深入拓展 1.从字节码说起 2.看看普通类在不同参数编译下的.class字节码里面都有什么 3.看看接口在不同参数编译下的.class字节码里面都有什么 五.结束 前言 在使用 Spring MVC 写Controller的时候,即使不使用注解,只要参数名和请求参数的key对应上了,就能自动完成数值

  • Java获取代码中方法参数名信息的方法

    前言 大家都知道随着java8的使用,在相应的方法签名中增加了新的对象Parameter,用于表示特定的参数信息,通过它的getName可以获取相应的参数名.即像在代码中编写的,如命名为username,那么在前台进行传参时,即不需要再编写如@Parameter("username")类的注解,而直接就能进行按名映射. 如下的代码参考所示: public class T { private interface T2 { void method(String username, Stri

  • ThinkPHP采用GET方式获取中文参数查询无结果的解决方法

    在用ThinkPHP做tags标签的时候,出现了一个问题,就是能获取到参数,但是查不出相应的结果.查看数据库发现数据是存在的.问题出在哪了呢? 形如http:/www.XXXX.com/tags/index/%E8%87%AA%E5%8A%A8%E9%AA%8C%E8%AF%81.html的调用 参数是经过urlencode()编码了的,使用urldecode()函数进行解码,再进行查询仍然没有结果. 紧接着测试转换编码iconv()函数,结果成功了. 浏览器默认的编码是GB2312的,而这个项

  • Laravel中获取路由参数Route Parameters的五种方法示例

    前言 大家都知道Laravel 获取路由参数的方式有很多,并且有个小坑,现汇总如下,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 假设我们设置了一个路由参数: /** * 定义路由参数名称分别为: param1,param2 */ Route::get('/{param1}/{param2}', 'TestController@index'); 现在我们访问 http://test.dev/1/2 在 TestController 中: /** * 路由参数获取方法 * *

  • C# 获取硬件参数的实现方法

    C# 获取硬件参数的实现方法 示例代码: private static string GetIdentifier(string wmiClass, string wmiProperty, string wmiMustBeTrue) { string result = ""; System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass); System.Management.M

  • AngularJS出现$http异步后台无法获取请求参数问题的解决方法

    本文实例讲述了AngularJS出现$http异步后台无法获取请求参数问题的解决方法.分享给大家供大家参考,具体如下: angular在通过异步提交数据时使用了与jQuery不一样的请求头部和数据序列化方式,导致部分后台程序无法正常解析数据. 原理分析(网上的分析): 对于AJAX应用(使用XMLHttpRequests)来说,向服务器发起请求的传统方式是:获取一个XMLHttpRequest对象的引用.发起请求.读取响应.检查状态码,最后处理服务端的响应.整个过程示例如下: var xmlht

随机推荐