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

 更新时间:2021年06月17日 10:06:59   作者:周水清  
这篇文章主要介绍了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 "";属性,可以获取到切入方法抛出的异常信息。

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

相关文章

  • Java内存溢出的几个区域总结(注意避坑!)

    Java内存溢出的几个区域总结(注意避坑!)

    内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能提供的最大内存,下面这篇文章主要给大家介绍了关于Java内存溢出的几个区域,总结出来给大家提醒注意避坑,需要的朋友可以参考下
    2022-11-11
  • java使用hadoop实现关联商品统计

    java使用hadoop实现关联商品统计

    本篇文章java使用hadoop实现关联商品统计,可以实现商品的关联统计,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2016-10-10
  • springcloud nacos动态线程池Dynamic tp配置接入实战详解

    springcloud nacos动态线程池Dynamic tp配置接入实战详解

    这篇文章主要为大家介绍了springcloud nacos动态线程池Dynamic tp配置接入实战详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 深入理解Spring中bean的生命周期介绍

    深入理解Spring中bean的生命周期介绍

    本篇文章主要介绍了深入理解Spring中bean的生命周期介绍,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • Spring boot 集成Dubbox的方法示例

    Spring boot 集成Dubbox的方法示例

    本篇文章主要介绍了Spring boot 集成Dubbox的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • 详谈Java泛型中T和问号(通配符)的区别

    详谈Java泛型中T和问号(通配符)的区别

    下面小编就为大家带来一篇详谈Java泛型中T和问号(通配符)的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • 详解Spring Cloud Gateway 限流操作

    详解Spring Cloud Gateway 限流操作

    这篇文章主要介绍了详解Spring Cloud Gateway 限流操作,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • Java多线程中断机制三种方法及示例

    Java多线程中断机制三种方法及示例

    这篇文章主要介绍了Java多线程中断机制三种方法及示例,向大家分享了这三种方法的介绍几代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • 详解Android开发中Fragment的使用

    详解Android开发中Fragment的使用

    这篇文章主要介绍了详解Android开发中Fragment的使用,包括Java代码中调用Fragment的方法,需要的朋友可以参考下
    2015-07-07
  • Java中两种抛出异常的方式示例详解

    Java中两种抛出异常的方式示例详解

    在Java中有两种抛出异常的方式,一种是throw,直接抛出异常,另一种是throws,间接抛出异常,本文给大家详细说明java中两种抛出异常的方式,感兴趣的朋友一起看看吧
    2023-08-08

最新评论