• 开始使用AspectJ-实现步骤@Aspect,@Before,还有其中的JoinPoint参数


    开始使用AspectJ

    1.maven依赖

    1. <dependency>
    2. <groupId>junitgroupId>
    3. <artifactId>junitartifactId>
    4. <version>4.11version>
    5. <scope>testscope>
    6. dependency>
    7. <dependency>
    8. <groupId>org.springframeworkgroupId>
    9. <artifactId>spring-contextartifactId>
    10. <version>5.2.5.RELEASEversion>
    11. dependency>
    12. <dependency>
    13. <groupId>org.springframeworkgroupId>
    14. <artifactId>spring-aspectsartifactId>
    15. <version>5.2.5.RELEASEversion>
    16. dependency>
    17. 插件
    18. <build>
    19. <plugins>
    20. <plugin>
    21. <artifactId>maven-compiler-pluginartifactId>
    22. <version>3.1version>
    23. <configuration>
    24. <source>1.8source>
    25. <target>1.8target>
    26. configuration>
    27. plugin>
    28. plugins>
    29. build>

    引入 AOP 约束

    在 AspectJ 实现 AOP 时,要引入 AOP 的约束。配置文件中使用的 AOP 约束中的标签, 均是 AspectJ 框架使用的,而非 Spring 框架本身在实现

    AOP 时使用的。 AspectJ 对于 AOP 的实现有注解和配置文件两种方式,常用是注解方式。

    2. AspectJ 基于注解的 AOP 实现(掌握)

    项目结构如下:

    2.1 实现步骤
    • Step1:定义业务接口与实现类

      接口:

      1. package com.bjpowernode.ba01;
      2. public interface SomeService {
      3. void doSome(String name,Integer age);
      4. }

      接口实现类:

      1. package com.bjpowernode.ba01;
      2. //目标类
      3. public class SomeServiceImpl implements SomeService {
      4. @Override
      5. public void doSome(String name,Integer age) {
      6. //给doSome方法增加一个功能,在doSome()执行之前, 输出方法的执行时间
      7. System.out.println("====目标方法doSome()====");
      8. }
      9. public void doOther(String name,Integer age) {
      10. //给doSome方法增加一个功能,在doSome()执行之前, 输出方法的执行时间
      11. System.out.println("====目标方法doSome()====");
      12. }
      13. }

      Step2:定义切面此时我们用的是 @Before

      1. package com.bjpowernode.ba01;
      2. import org.aspectj.lang.JoinPoint;
      3. import org.aspectj.lang.annotation.Aspect;
      4. import org.aspectj.lang.annotation.Before;
      5. import java.util.Date;
      6. /**
      7. * @Aspect : 是aspectj框架中的注解。
      8. * 作用:表示当前类是切面类。
      9. * 切面类:是用来给业务方法增加功能的类,在这个类中有切面的功能代码
      10. * 位置:在类定义的上面
      11. */
      12. @Aspect
      13. public class MyAspect {
      14. /**
      15. * 定义方法,方法是实现切面功能的。
      16. * 方法的定义要求:
      17. * 1.公共方法 public
      18. * 2.方法没有返回值
      19. * 3.方法名称自定义
      20. * 4.方法可以有参数,也可以没有参数。
      21. * 如果有参数,参数不是自定义的,有几个参数类型可以使用。
      22. */
      23. /**
      24. * @Before: 前置通知注解
      25. * 属性:value ,是切入点表达式,表示切面的功能执行的位置。
      26. * 位置:在方法的上面
      27. * 特点:
      28. * 1.在目标方法之前先执行的
      29. * 2.不会改变目标方法的执行结果
      30. * 3.不会影响目标方法的执行。
      31. */
      32. @Before(value = "execution(public void com.bjpowernode.ba01.SomeServiceImpl.doSome(String,Integer))")
      33. public void myBefore(){
      34. //就是你切面要执行的功能代码
      35. System.out.println("前置通知, 切面功能:在目标方法之前输出执行时间:"+ new Date());
      36. }
      37. //可以省略 public
      38. /*@Before(value = "execution(void com.bjpowernode.ba01.SomeServiceImpl.doSome(String,Integer))")
      39. public void myBefore(){
      40. //就是你切面要执行的功能代码
      41. System.out.println("1=====前置通知, 切面功能:在目标方法之前输出执行时间:"+ new Date());
      42. }*/
      43. //使用 <*..>的方法表明不管上级多少目录的SomeServiceImpl的方法
      44. /* @Before(value = "execution(void *..SomeServiceImpl.doSome(String,Integer))")
      45. public void myBefore(){
      46. //就是你切面要执行的功能代码
      47. System.out.println("2=====前置通知, 切面功能:在目标方法之前输出执行时间:"+ new Date());
      48. }*/
      49. //其中返回值也可以用 * 号代替
      50. /*@Before(value = "execution(* *..SomeServiceImpl.*(..))")
      51. public void myBefore(){
      52. //就是你切面要执行的功能代码
      53. System.out.println("3=====前置通知, 切面功能:在目标方法之前输出执行时间:"+ new Date());
      54. }*/
      55. //可以使用 * 号作为通配符,只要是do开头的都可以被动态代理识别
      56. /*@Before(value = "execution(* do*(..))")
      57. public void myBefore2(){
      58. //就是你切面要执行的功能代码
      59. System.out.println("4=====前置通知, 切面功能:在目标方法之前输出执行时间:"+ new Date());
      60. }*/
      61. //形式参数可以被 <..> 代替
      62. /*@Before(value = "execution(* com.bjpowernode.ba01.*ServiceImpl.*(..))")
      63. public void myBefore2(){
      64. //就是你切面要执行的功能代码
      65. System.out.println("2=====前置通知, 切面功能:在目标方法之前输出执行时间:"+ new Date());
      66. }*/
      67. }

      Step3:声明目标对象切面类对象 此时我们用的配置文件,在文件种需要注册aspectj的自动代理生成器对象

      在定义好切面 Aspect 后,需要通知 Spring 容器,让容器生成“目标类+ 切面”的代理 对象。这个代理是由容器自动生成的。只需要在 Spring 配置文件中注册一个基于 aspectj 的 自动代理生成器,其就会自动扫描到@Aspect 注解,并按通知类型与切入点,将其织入,并 生成代理。

      1. "1.0" encoding="UTF-8"?>
      2. <beans xmlns="http://www.springframework.org/schema/beans"
      3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      4. xmlns:aop="http://www.springframework.org/schema/aop"
      5. xsi:schemaLocation="http://www.springframework.org/schema/beans
      6. http://www.springframework.org/schema/beans/spring-beans.xsd
      7. http://www.springframework.org/schema/aop
      8. https://www.springframework.org/schema/aop/spring-aop.xsd">
      9. <bean id="someService" class="com.bjpowernode.ba01.SomeServiceImpl" />
      10. <bean id="myAspect" class="com.bjpowernode.ba01.MyAspect" />
      11. <aop:aspectj-autoproxy />
      12. beans>

    2.2 [掌握]@Before 前置通知-方法有 JoinPoint 参数

    在目标方法执行之前执行。被注解为前置通知的方法,可以包含一个 JoinPoint 类型参 数。该类型的对象本身就是切入点表达式。通过该参数,可获取切入点表达式、方法签名、 目标对象等。 不光前置通知的方法,可以包含一个 JoinPoint 类型参数,所有的通知方法均可包含该 参数。

    1. package com.bjpowernode.ba01;
    2. import org.aspectj.lang.JoinPoint;
    3. import org.aspectj.lang.annotation.Aspect;
    4. import org.aspectj.lang.annotation.Before;
    5. import java.util.Date;
    6. /**
    7. * @Aspect : 是aspectj框架中的注解。
    8. * 作用:表示当前类是切面类。
    9. * 切面类:是用来给业务方法增加功能的类,在这个类中有切面的功能代码
    10. * 位置:在类定义的上面
    11. */
    12. @Aspect
    13. public class MyAspect {
    14. /**
    15. * 定义方法,方法是实现切面功能的。
    16. * 方法的定义要求:
    17. * 1.公共方法 public
    18. * 2.方法没有返回值
    19. * 3.方法名称自定义
    20. * 4.方法可以有参数,也可以没有参数。
    21. * 如果有参数,参数不是自定义的,有几个参数类型可以使用。
    22. */
    23. /**
    24. * @Before: 前置通知注解
    25. * 属性:value ,是切入点表达式,表示切面的功能执行的位置。
    26. * 位置:在方法的上面
    27. * 特点:
    28. * 1.在目标方法之前先执行的
    29. * 2.不会改变目标方法的执行结果
    30. * 3.不会影响目标方法的执行。
    31. */
    32. /**
    33. * 指定通知方法中的参数 : JoinPoint
    34. * JoinPoint:业务方法,要加入切面功能的业务方法
    35. * 作用是:可以在通知方法中获取方法执行时的信息, 例如方法名称,方法的实参。
    36. * 如果你的切面功能中需要用到方法的信息,就加入JoinPoint.
    37. * 这个JoinPoint参数的值是由框架赋予, 必须是第一个位置的参数
    38. */
    39. @Before(value = "execution(void *..SomeServiceImpl.doSome(String,Integer))")
    40. public void myBefore(JoinPoint jp){
    41. //获取方法的完整定义
    42. System.out.println("方法的签名(定义)="+jp.getSignature());
    43. System.out.println("方法的名称="+jp.getSignature().getName());
    44. //获取方法的实参
    45. Object args [] = jp.getArgs();
    46. for (Object arg:args){
    47. System.out.println("参数="+arg);
    48. }
    49. //就是你切面要执行的功能代码
    50. System.out.println("2=====前置通知, 切面功能:在目标方法之前输出执行时间:"+ new Date());
    51. }
    52. }

    代码执行结果如下;(执行的还是上述方法)

  • 相关阅读:
    Java Double isInfinite(double v)方法具有什么功能呢?
    有什么可以自动保存微信文件的方法么?
    Win软件 - (Net-Framework)已处理证书链,但是在不受信任提供程序信任的根证书中终止
    【牛客刷题】带你在牛客刷题第二弹(简单排序)
    vscode - 环境准备 - 修改缓存路径
    Spring整合MyBatis和Junit(十一)
    Window系统安装RocketMQ
    使用FileZilla连接本地和服务器进行文件传输
    MySQL索引详解
    springboot爱护大自然的设计与实现毕业设计源码231643
  • 原文地址:https://blog.csdn.net/weixin_48370579/article/details/127711908