SpringBoot项目中使用AOP的方法

 更新时间:2018年02月22日 16:12:45   作者:QiHY  
本篇文章主要介绍了SpringBoot项目中使用AOP的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

本文介绍了SpringBoot项目中使用AOP的方法,分享给大家,具体如下:

1.概述

将通用的逻辑用AOP技术实现可以极大的简化程序的编写,例如验签、鉴权等。Spring的声明式事务也是通过AOP技术实现的。

具体的代码参照 示例项目 https://github.com/qihaiyan/springcamp/tree/master/spring-aop

Spring的AOP技术主要有4个核心概念:

Pointcut: 切点,用于定义哪个方法会被拦截,例如 execution(* cn.springcamp.springaop.service.*.*(..))

Advice: 拦截到方法后要执行的动作

Aspect: 切面,把Pointcut和Advice组合在一起形成一个切面

Join Point: 在执行时Pointcut的一个实例

Weaver: 实现AOP的框架,例如 AspectJ 或 Spring AOP

2. 切点定义

常用的Pointcut定义有 execution 和 @annotation 两种。execution 定义对方法无侵入,用于实现比较通用的切面。@annotation 可以作为注解加到特定的方法上,例如Spring的Transaction注解。

execution切点定义应该放在一个公共的类中,集中管理切点定义。

示例:

public class CommonJoinPointConfig {
  @Pointcut("execution(* cn.springcamp.springaop.service.*.*(..))")
  public void serviceLayerExecution() {}
}

这样在具体的Aspect类中可以通过 CommonJoinPointConfig.serviceLayerExecution()来引用切点。

public class BeforeAspect {
  @Before("CommonJoinPointConfig.serviceLayerExecution()")
  public void before(JoinPoint joinPoint) {
    System.out.println(" -------------> Before Aspect ");
    System.out.println(" -------------> before execution of " + joinPoint);
  }
}

当切点需要改变时,只需修改CommonJoinPointConfig类即可,不用修改每个Aspect类。

3. 常用的切面

Before: 在方法执行之前执行Advice,常用于验签、鉴权等。

After: 在方法执行完成后执行,无论是执行成功还是抛出异常.

AfterReturning: 仅在方法执行成功后执行.

AfterThrowing: 仅在方法执抛出异常后执行.

一个简单的Aspect:

@Aspect
@Component
public class BeforeAspect {
  @Before("CommonJoinPointConfig.serviceLayerExecution()")
  public void before(JoinPoint joinPoint) {
    System.out.println(" -------------> Before Aspect ");
    System.out.println(" -------------> before execution of " + joinPoint);
  }
}

4. 自定义注解

假设我们想收集特定方法的执行时间,一种比较合理的方式是自定义一个注解,然后在需要收集执行时间的方法上加上这个注解。

首先定义一个注解TrackTime:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TrackTime {
  String param() default "";
}

然后再定义一个Aspect类,用于实现注解的行为:

@Aspect
@Component
public class TrackTimeAspect {
  @Around("@annotation(trackTime)")
  public Object around(ProceedingJoinPoint joinPoint, TrackTime trackTime) throws Throwable {
    Object result = null;
    long startTime = System.currentTimeMillis();
    result = joinPoint.proceed();
    long timeTaken = System.currentTimeMillis() - startTime;
    System.out.println(" -------------> Time Taken by " + joinPoint + " with param[" + trackTime.param() + "] is " + timeTaken);
    return result;
  }
}

在某个方法上使用这个注解,就可以收集这个方法的执行时间:

@TrackTime(param = "myService")
public String runFoo() {
  System.out.println(" -------------> foo");
  return "foo";
}

注意 @TrackTime(param = "myService") 注解是可以传参的。

为了让注解可以传参数,需要在定义注解时指定一个参数String param() default "默认值",

同时在Aspect类中,around方法上加上相应的参数,@Around注解中也需要用参数的变量名trackTime,而不能用类名TrackTime。

@Around("@annotation(trackTime)")
public Object around(ProceedingJoinPoint joinPoint, TrackTime trackTime)

5.总结

在运行示例项目时,控制台会输出以下内容:

 -------------> Before Aspect
 -------------> before execution of execution(String cn.springcamp.springaop.service.MyService.runFoo())
 -------------> foo
 -------------> Time Taken by execution(String cn.springcamp.springaop.service.MyService.runFoo()) with param[myService] is 8
 -------------> After Aspect
 -------------> after execution of execution(String cn.springcamp.springaop.service.MyService.runFoo())
 -------------> AfterReturning Aspect
 -------------> execution(String cn.springcamp.springaop.service.MyService.runFoo()) returned with value foo

可以看出几种 Aspect 的执行顺序依次为 Before After Around AfterReturning(AfterThrowing)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java实现inputstream流的复制代码实例

    Java实现inputstream流的复制代码实例

    这篇文章主要介绍了Java实现inputstream流的复制代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Java编程中的vector类用法学习笔记

    Java编程中的vector类用法学习笔记

    Vector通常被用来实现动态数组,即可实现自动增长的对象数组,和C++一样vector类同样被Java内置,下面就来看一下vector类的基本用法.
    2016-05-05
  • EasyExcel如何导出多级且动态的表头

    EasyExcel如何导出多级且动态的表头

    文章介绍了使用EasyExcel库实现Excel多级表头导出的步骤,包括创建表头集合、导出数据集合、设置样式和列宽,以及自动合并表头和测试导出
    2026-01-01
  • spring boot项目快速构建的全步骤

    spring boot项目快速构建的全步骤

    这篇文章主要给大家介绍了关于spring boot项目快速构建的全步骤,文中通过示例代码介绍的非常详细,对大家学习或者使用spring boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • Java中的复合数据类型

    Java中的复合数据类型

    这篇文章主要介绍了Java中的复合数据类型,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Java基础之自定义类加载器

    Java基础之自定义类加载器

    应该有很多小伙伴还不了解Java自定义类加载器吧,下文中有对Java自定义类加载器非常详细的描述,还有小伙伴们最喜欢的代码环节,需要的朋友可以参考下
    2021-05-05
  • mall整合SpringSecurity及JWT认证授权实战下

    mall整合SpringSecurity及JWT认证授权实战下

    这篇文章主要为大家介绍了mall整合SpringSecurity及JWT认证授权实战第二篇,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Java中输入被跳过情况的深入探究

    Java中输入被跳过情况的深入探究

    这篇文章主要给大家介绍了关于Java中输入被跳过情况的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Java 获取本机的IP与MAC地址实现详解

    Java 获取本机的IP与MAC地址实现详解

    这篇文章主要介绍了Java 获取本机的IP与MAC地址实现详解的相关资料,需要的朋友可以参考下
    2016-09-09
  • 如何把Java程序窗口在屏幕中间显示

    如何把Java程序窗口在屏幕中间显示

    大家在日常Java开发中,可能会需要把程序窗口定位在屏幕中间,那该如何操作呢,下面来一起看看。
    2016-08-08

最新评论