• (续)SSM整合之spring笔记(AOP 基于注解的AOP之各种通知使用,环绕通知,切面的优先级)(P103—P104)


    一 .各种通知使用

    前置通知:使用 @Before 注解标识,在被代理的目标方法 执行
    返回通知:使用 @AfterReturning 注解标识,在被代理的目标方法 成功结束 后执行( 寿终正寝
    异常通知:使用 @AfterThrowing 注解标识,在被代理的目标方法 异常结束 后执行( 死于非命
    后置通知:使用 @After 注解标识,在被代理的目标方法 最终结束 后执行( 盖棺定论
    环绕通知:使用 @Around 注解标识,使用 try...catch...finally 结构围绕 整个 被代理的目标方法,包
    括上面四种通知对应的所有位置
    各种通知的执行顺序:
    Spring 版本 5.3.x 以前:
    前置通知
    目标操作
    后置通知
    返回通知或异常通知
    Spring 版本 5.3.x 以后:
    前置通知
    目标操作
    返回通知或异常通知
    后置通知

    1 . 后置通知

    测试  后置通知在哪个语句里面执行 

    @After:后置通知,在目标对象方法的finally字句中执行

    1. package com.atguigu.spring.aop.annotation;
    2. import org.aspectj.lang.JoinPoint;
    3. import org.aspectj.lang.Signature;
    4. import org.aspectj.lang.annotation.After;
    5. import org.aspectj.lang.annotation.Aspect;
    6. import org.aspectj.lang.annotation.Before;
    7. import org.aspectj.lang.annotation.Pointcut;
    8. import org.springframework.stereotype.Component;
    9. import java.util.Arrays;
    10. /**
    11. * Date:2022/7/4
    12. * Author:ybc
    13. * Description:
    14. * 1、在切面中,需要通过指定的注解将方法标识为通知方法
    15. * @Before:前置通知,在目标对象方法执行之前执行
    16. * @After:后置通知,在目标对象方法的finally字句中执行
    17. *
    18. * 2、切入点表达式:设置在标识通知的注解的value属性中
    19. * execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int)
    20. * execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..)
    21. * 第一个*表示任意的访问修饰符和返回值类型
    22. * 第二个*表示类中任意的方法
    23. * ..表示任意的参数列表
    24. * 类的地方也可以使用*,表示包下所有的类
    25. * 3、重用切入点表达式
    26. * //@Pointcut声明一个公共的切入点表达式
    27. * @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    28. * public void pointCut(){}
    29. * 使用方式:@Before("pointCut()")
    30. *
    31. * 4、获取连接点的信息
    32. * 在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息
    33. * //获取连接点所对应方法的签名信息
    34. * Signature signature = joinPoint.getSignature();
    35. * //获取连接点所对应方法的参数
    36. * Object[] args = joinPoint.getArgs();
    37. *
    38. */
    39. @Component
    40. @Aspect //将当前组件标识为切面
    41. public class LoggerAspect {
    42. @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    43. public void pointCut(){}
    44. //@Before("execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int))")
    45. //@Before("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    46. @Before("pointCut()")
    47. public void beforeAdviceMethod(JoinPoint joinPoint) {
    48. //获取连接点所对应方法的签名信息
    49. Signature signature = joinPoint.getSignature();
    50. //获取连接点所对应方法的参数
    51. Object[] args = joinPoint.getArgs();
    52. System.out.println("LoggerAspect,方法:"+signature.getName()+",参数:"+ Arrays.toString(args));
    53. }
    54. @After("pointCut()")
    55. public void afterAdviceMethod(){
    56. System.out.println("LoggerAspect,后置通知");
    57. }
    58. }

    测试

    1. public class AOPByAnnotationTest {
    2. @Test
    3. public void testAOPByAnnotation(){
    4. //获取IOC容器
    5. ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml");
    6. //获取目标对象
    7. // CalculatorImpl calculator = ioc.getBean(CalculatorImpl.class);
    8. //获取代理对象
    9. Calculator calculator = ioc.getBean(Calculator.class);
    10. calculator.div(1, 0);
    11. }
    12. }

     添加连接点

    1. /**
    2. * 1、在切面中,需要通过指定的注解将方法标识为通知方法
    3. * @Before:前置通知,在目标对象方法执行之前执行
    4. * @After:后置通知,在目标对象方法的finally字句中执行
    5. *
    6. * 2、切入点表达式:设置在标识通知的注解的value属性中
    7. * execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int)
    8. * execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..)
    9. * 第一个*表示任意的访问修饰符和返回值类型
    10. * 第二个*表示类中任意的方法
    11. * ..表示任意的参数列表
    12. * 类的地方也可以使用*,表示包下所有的类
    13. * 3、重用切入点表达式
    14. * //@Pointcut声明一个公共的切入点表达式
    15. * @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    16. * public void pointCut(){}
    17. * 使用方式:@Before("pointCut()")
    18. *
    19. * 4、获取连接点的信息
    20. * 在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息
    21. * //获取连接点所对应方法的签名信息
    22. * Signature signature = joinPoint.getSignature();
    23. * //获取连接点所对应方法的参数
    24. * Object[] args = joinPoint.getArgs();
    25. *
    26. */
    27. @Component
    28. @Aspect //将当前组件标识为切面
    29. public class LoggerAspect {
    30. @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    31. public void pointCut(){}
    32. //@Before("execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int))")
    33. //@Before("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    34. @Before("pointCut()")
    35. public void beforeAdviceMethod(JoinPoint joinPoint) {
    36. //获取连接点所对应方法的签名信息
    37. Signature signature = joinPoint.getSignature();
    38. //获取连接点所对应方法的参数
    39. Object[] args = joinPoint.getArgs();
    40. System.out.println("LoggerAspect,方法:"+signature.getName()+",参数:"+ Arrays.toString(args));
    41. }
    42. @After("pointCut()")
    43. public void afterAdviceMethod(JoinPoint joinPoint){
    44. // System.out.println("LoggerAspect,后置通知");
    45. //获取连接点所对应方法的签名信息
    46. Signature signature = joinPoint.getSignature();
    47. System.out.println("LoggerAspect,方法:"+signature.getName()+",执行完毕");
    48. }
    49. }

     

    2 . 返回通知

    测试有没有输出

    1. /**
    2. * 1、在切面中,需要通过指定的注解将方法标识为通知方法
    3. * @Before:前置通知,在目标对象方法执行之前执行
    4. * @After:后置通知,在目标对象方法的finally字句中执行
    5. @AfterReturning:返回通知,在目标对象方法返回值之后执行
    6. *
    7. * 2、切入点表达式:设置在标识通知的注解的value属性中
    8. * execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int)
    9. * execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..)
    10. * 第一个*表示任意的访问修饰符和返回值类型
    11. * 第二个*表示类中任意的方法
    12. * ..表示任意的参数列表
    13. * 类的地方也可以使用*,表示包下所有的类
    14. * 3、重用切入点表达式
    15. * //@Pointcut声明一个公共的切入点表达式
    16. * @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    17. * public void pointCut(){}
    18. * 使用方式:@Before("pointCut()")
    19. *
    20. * 4、获取连接点的信息
    21. * 在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息
    22. * //获取连接点所对应方法的签名信息
    23. * Signature signature = joinPoint.getSignature();
    24. * //获取连接点所对应方法的参数
    25. * Object[] args = joinPoint.getArgs();
    26. *
    27. */
    28. @Component
    29. @Aspect //将当前组件标识为切面
    30. public class LoggerAspect {
    31. @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    32. public void pointCut(){}
    33. //前置通知
    34. //@Before("execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int))")
    35. //@Before("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    36. @Before("pointCut()")
    37. public void beforeAdviceMethod(JoinPoint joinPoint) {
    38. //获取连接点所对应方法的签名信息
    39. Signature signature = joinPoint.getSignature();
    40. //获取连接点所对应方法的参数
    41. Object[] args = joinPoint.getArgs();
    42. System.out.println("LoggerAspect,方法:"+signature.getName()+",参数:"+ Arrays.toString(args));
    43. }
    44. //后置通知
    45. @After("pointCut()")
    46. public void afterAdviceMethod(JoinPoint joinPoint){
    47. // System.out.println("LoggerAspect,后置通知");
    48. //获取连接点所对应方法的签名信息
    49. Signature signature = joinPoint.getSignature();
    50. System.out.println("LoggerAspect,方法:"+signature.getName()+",执行完毕");
    51. }
    52. //返回通知
    53. @AfterReturning("pointCut()")
    54. public void afterReturningAdviceMethod(){
    55. System.out.println("LoggerAspect,返回通知");
    56. }
    57. }

     

    测试:

    1. public class AOPByAnnotationTest {
    2. @Test
    3. public void testAOPByAnnotation(){
    4. //获取IOC容器
    5. ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml");
    6. //获取目标对象
    7. // CalculatorImpl calculator = ioc.getBean(CalculatorImpl.class);
    8. //获取代理对象
    9. Calculator calculator = ioc.getBean(Calculator.class);
    10. calculator.div(1, 0);
    11. }
    12. }

    并没有输出返回通知  因为方法执行过程出现了异常  有了异常 所以没有返回值  

    返回通知是在有返回的时候执行的   因为有了异常 没有返回值  所以执行返回通知

    我们把发生异常的地方修改下  修改后如下

    1. public class AOPByAnnotationTest {
    2. @Test
    3. public void testAOPByAnnotation(){
    4. //获取IOC容器
    5. ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml");
    6. //获取目标对象
    7. // CalculatorImpl calculator = ioc.getBean(CalculatorImpl.class);
    8. //获取代理对象
    9. Calculator calculator = ioc.getBean(Calculator.class);
    10. calculator.div(1, 1);
    11. }
    12. }

     

    1. /**
    2. * 1、在切面中,需要通过指定的注解将方法标识为通知方法
    3. * @Before:前置通知,在目标对象方法执行之前执行
    4. * @After:后置通知,在目标对象方法的finally字句中执行
    5. * @AfterReturning:返回通知,在目标对象方法返回值之后执行
    6. *
    7. * 2、切入点表达式:设置在标识通知的注解的value属性中
    8. * execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int)
    9. * execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..)
    10. * 第一个*表示任意的访问修饰符和返回值类型
    11. * 第二个*表示类中任意的方法
    12. * ..表示任意的参数列表
    13. * 类的地方也可以使用*,表示包下所有的类
    14. * 3、重用切入点表达式
    15. * //@Pointcut声明一个公共的切入点表达式
    16. * @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    17. * public void pointCut(){}
    18. * 使用方式:@Before("pointCut()")
    19. *
    20. * 4、获取连接点的信息
    21. * 在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息
    22. * //获取连接点所对应方法的签名信息
    23. * Signature signature = joinPoint.getSignature();
    24. * //获取连接点所对应方法的参数
    25. * Object[] args = joinPoint.getArgs();
    26. *
    27. */
    28. @Component
    29. @Aspect //将当前组件标识为切面
    30. public class LoggerAspect {
    31. @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    32. public void pointCut(){}
    33. //前置通知
    34. //@Before("execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int))")
    35. //@Before("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    36. @Before("pointCut()")
    37. public void beforeAdviceMethod(JoinPoint joinPoint) {
    38. //获取连接点所对应方法的签名信息
    39. Signature signature = joinPoint.getSignature();
    40. //获取连接点所对应方法的参数
    41. Object[] args = joinPoint.getArgs();
    42. System.out.println("LoggerAspect,方法:"+signature.getName()+",参数:"+ Arrays.toString(args));
    43. }
    44. //后置通知
    45. @After("pointCut()")
    46. public void afterAdviceMethod(JoinPoint joinPoint){
    47. // System.out.println("LoggerAspect,后置通知");
    48. //获取连接点所对应方法的签名信息
    49. Signature signature = joinPoint.getSignature();
    50. System.out.println("LoggerAspect,方法:"+signature.getName()+",执行完毕");
    51. }
    52. //返回通知
    53. /**
    54. * 在返回通知中若要获取目标对象方法的返回值
    55. * 只需要通过@AfterReturning注解的returning属性
    56. * 就可以将通知方法的某个参数指定为接收目标对象方法的返回值的参数
    57. */
    58. @AfterReturning(value = "pointCut()", returning = "result")
    59. public void afterReturningAdviceMethod(JoinPoint joinPoint, Object result){
    60. // System.out.println("LoggerAspect,返回通知");
    61. //获取连接点所对应方法的签名信息
    62. Signature signature = joinPoint.getSignature();
    63. System.out.println("LoggerAspect,方法:"+signature.getName()+",结果:"+result);
    64. }
    65. }

    3 .异常通知

    1. /*
    2. * 1、在切面中,需要通过指定的注解将方法标识为通知方法
    3. * @Before:前置通知,在目标对象方法执行之前执行
    4. * @After:后置通知,在目标对象方法的finally字句中执行
    5. * @AfterReturning:返回通知,在目标对象方法返回值之后执行
    6. * @AfterThrowing:异常通知,在目标对象方法的catch字句中执行
    7. *
    8. * 2、切入点表达式:设置在标识通知的注解的value属性中
    9. * execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int)
    10. * execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..)
    11. * 第一个*表示任意的访问修饰符和返回值类型
    12. * 第二个*表示类中任意的方法
    13. * ..表示任意的参数列表
    14. * 类的地方也可以使用*,表示包下所有的类
    15. * 3、重用切入点表达式
    16. * //@Pointcut声明一个公共的切入点表达式
    17. * @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    18. * public void pointCut(){}
    19. * 使用方式:@Before("pointCut()")
    20. *
    21. * 4、获取连接点的信息
    22. * 在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息
    23. * //获取连接点所对应方法的签名信息
    24. * Signature signature = joinPoint.getSignature();
    25. * //获取连接点所对应方法的参数
    26. * Object[] args = joinPoint.getArgs();
    27. *
    28. */
    29. @Component
    30. @Aspect //将当前组件标识为切面
    31. public class LoggerAspect {
    32. @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    33. public void pointCut(){}
    34. //前置通知
    35. //@Before("execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int))")
    36. //@Before("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    37. @Before("pointCut()")
    38. public void beforeAdviceMethod(JoinPoint joinPoint) {
    39. //获取连接点所对应方法的签名信息
    40. Signature signature = joinPoint.getSignature();
    41. //获取连接点所对应方法的参数
    42. Object[] args = joinPoint.getArgs();
    43. System.out.println("LoggerAspect,方法:"+signature.getName()+",参数:"+ Arrays.toString(args));
    44. }
    45. //后置通知
    46. @After("pointCut()")
    47. public void afterAdviceMethod(JoinPoint joinPoint){
    48. // System.out.println("LoggerAspect,后置通知");
    49. //获取连接点所对应方法的签名信息
    50. Signature signature = joinPoint.getSignature();
    51. System.out.println("LoggerAspect,方法:"+signature.getName()+",执行完毕");
    52. }
    53. //返回通知
    54. /**
    55. * 在返回通知中若要获取目标对象方法的返回值
    56. * 只需要通过@AfterReturning注解的returning属性
    57. * 就可以将通知方法的某个参数指定为接收目标对象方法的返回值的参数
    58. */
    59. @AfterReturning(value = "pointCut()", returning = "result")
    60. public void afterReturningAdviceMethod(JoinPoint joinPoint, Object result){
    61. // System.out.println("LoggerAspect,返回通知");
    62. //获取连接点所对应方法的签名信息
    63. Signature signature = joinPoint.getSignature();
    64. System.out.println("LoggerAspect,方法:"+signature.getName()+",结果:"+result);
    65. }
    66. //异常通知
    67. @AfterThrowing( "pointCut()")
    68. public void afterThrowingAdviceMethod(JoinPoint joinPoint){
    69. //获取连接点所对应方法的签名信息
    70. Signature signature = joinPoint.getSignature();
    71. System.out.println("LoggerAspect,方法:"+signature.getName()+",异常通知");
    72. }
    73. }

     

     测试:

    1. public class AOPByAnnotationTest {
    2. @Test
    3. public void testAOPByAnnotation(){
    4. //获取IOC容器
    5. ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml");
    6. //获取目标对象
    7. // CalculatorImpl calculator = ioc.getBean(CalculatorImpl.class);
    8. //获取代理对象
    9. Calculator calculator = ioc.getBean(Calculator.class);
    10. calculator.div(1, 0);
    11. }
    12. }

    获取异常

    1. /**
    2. * 1、在切面中,需要通过指定的注解将方法标识为通知方法
    3. * @Before:前置通知,在目标对象方法执行之前执行
    4. * @After:后置通知,在目标对象方法的finally字句中执行
    5. * @AfterReturning:返回通知,在目标对象方法返回值之后执行
    6. * @AfterThrowing:异常通知,在目标对象方法的catch字句中执行
    7. *
    8. * 2、切入点表达式:设置在标识通知的注解的value属性中
    9. * execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int)
    10. * execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..)
    11. * 第一个*表示任意的访问修饰符和返回值类型
    12. * 第二个*表示类中任意的方法
    13. * ..表示任意的参数列表
    14. * 类的地方也可以使用*,表示包下所有的类
    15. * 3、重用切入点表达式
    16. * //@Pointcut声明一个公共的切入点表达式
    17. * @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    18. * public void pointCut(){}
    19. * 使用方式:@Before("pointCut()")
    20. *
    21. * 4、获取连接点的信息
    22. * 在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息
    23. * //获取连接点所对应方法的签名信息
    24. * Signature signature = joinPoint.getSignature();
    25. * //获取连接点所对应方法的参数
    26. * Object[] args = joinPoint.getArgs();
    27. *
    28. */
    29. @Component
    30. @Aspect //将当前组件标识为切面
    31. public class LoggerAspect {
    32. @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    33. public void pointCut(){}
    34. //前置通知
    35. //@Before("execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int))")
    36. //@Before("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    37. @Before("pointCut()")
    38. public void beforeAdviceMethod(JoinPoint joinPoint) {
    39. //获取连接点所对应方法的签名信息
    40. Signature signature = joinPoint.getSignature();
    41. //获取连接点所对应方法的参数
    42. Object[] args = joinPoint.getArgs();
    43. System.out.println("LoggerAspect,方法:"+signature.getName()+",参数:"+ Arrays.toString(args));
    44. }
    45. //后置通知
    46. @After("pointCut()")
    47. public void afterAdviceMethod(JoinPoint joinPoint){
    48. // System.out.println("LoggerAspect,后置通知");
    49. //获取连接点所对应方法的签名信息
    50. Signature signature = joinPoint.getSignature();
    51. System.out.println("LoggerAspect,方法:"+signature.getName()+",执行完毕");
    52. }
    53. //返回通知
    54. /**
    55. * 在返回通知中若要获取目标对象方法的返回值
    56. * 只需要通过@AfterReturning注解的returning属性
    57. * 就可以将通知方法的某个参数指定为接收目标对象方法的返回值的参数
    58. */
    59. @AfterReturning(value = "pointCut()", returning = "result")
    60. public void afterReturningAdviceMethod(JoinPoint joinPoint, Object result){
    61. // System.out.println("LoggerAspect,返回通知");
    62. //获取连接点所对应方法的签名信息
    63. Signature signature = joinPoint.getSignature();
    64. System.out.println("LoggerAspect,方法:"+signature.getName()+",结果:"+result);
    65. }
    66. //异常通知
    67. /* @AfterThrowing( "pointCut()")
    68. public void afterThrowingAdviceMethod(JoinPoint joinPoint){
    69. //获取连接点所对应方法的签名信息
    70. Signature signature = joinPoint.getSignature();
    71. System.out.println("LoggerAspect,方法:"+signature.getName()+",异常通知");
    72. }*/
    73. /**
    74. * 在异常通知中若要获取目标对象方法的异常
    75. * 只需要通过AfterThrowing注解的throwing属性
    76. * 就可以将通知方法的某个参数指定为接收目标对象方法出现的异常的参数
    77. */
    78. @AfterThrowing(value = "pointCut()", throwing = "ex")
    79. public void afterThrowingAdviceMethod(JoinPoint joinPoint, Throwable ex){
    80. //获取连接点所对应方法的签名信息
    81. Signature signature = joinPoint.getSignature();
    82. System.out.println("LoggerAspect,方法:"+signature.getName()+",异常:"+ex);
    83. }
    84. }

     

    4 . 环绕通知

    1. /**
    2. * 1、在切面中,需要通过指定的注解将方法标识为通知方法
    3. * @Before:前置通知,在目标对象方法执行之前执行
    4. * @After:后置通知,在目标对象方法的finally字句中执行
    5. * @AfterReturning:返回通知,在目标对象方法返回值之后执行
    6. * @AfterThrowing:异常通知,在目标对象方法的catch字句中执行
    7. *
    8. * 2、切入点表达式:设置在标识通知的注解的value属性中
    9. * execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int)
    10. * execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..)
    11. * 第一个*表示任意的访问修饰符和返回值类型
    12. * 第二个*表示类中任意的方法
    13. * ..表示任意的参数列表
    14. * 类的地方也可以使用*,表示包下所有的类
    15. * 3、重用切入点表达式
    16. * //@Pointcut声明一个公共的切入点表达式
    17. * @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    18. * public void pointCut(){}
    19. * 使用方式:@Before("pointCut()")
    20. *
    21. * 4、获取连接点的信息
    22. * 在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息
    23. * //获取连接点所对应方法的签名信息
    24. * Signature signature = joinPoint.getSignature();
    25. * //获取连接点所对应方法的参数
    26. * Object[] args = joinPoint.getArgs();
    27. *
    28. */
    29. @Component
    30. @Aspect //将当前组件标识为切面
    31. public class LoggerAspect {
    32. @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    33. public void pointCut(){}
    34. //前置通知
    35. //@Before("execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int))")
    36. //@Before("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    37. @Before("pointCut()")
    38. public void beforeAdviceMethod(JoinPoint joinPoint) {
    39. //获取连接点所对应方法的签名信息
    40. Signature signature = joinPoint.getSignature();
    41. //获取连接点所对应方法的参数
    42. Object[] args = joinPoint.getArgs();
    43. System.out.println("LoggerAspect,方法:"+signature.getName()+",参数:"+ Arrays.toString(args));
    44. }
    45. //后置通知
    46. @After("pointCut()")
    47. public void afterAdviceMethod(JoinPoint joinPoint){
    48. // System.out.println("LoggerAspect,后置通知");
    49. //获取连接点所对应方法的签名信息
    50. Signature signature = joinPoint.getSignature();
    51. System.out.println("LoggerAspect,方法:"+signature.getName()+",执行完毕");
    52. }
    53. //返回通知
    54. /**
    55. * 在返回通知中若要获取目标对象方法的返回值
    56. * 只需要通过@AfterReturning注解的returning属性
    57. * 就可以将通知方法的某个参数指定为接收目标对象方法的返回值的参数
    58. */
    59. @AfterReturning(value = "pointCut()", returning = "result")
    60. public void afterReturningAdviceMethod(JoinPoint joinPoint, Object result){
    61. // System.out.println("LoggerAspect,返回通知");
    62. //获取连接点所对应方法的签名信息
    63. Signature signature = joinPoint.getSignature();
    64. System.out.println("LoggerAspect,方法:"+signature.getName()+",结果:"+result);
    65. }
    66. //异常通知
    67. /* @AfterThrowing( "pointCut()")
    68. public void afterThrowingAdviceMethod(JoinPoint joinPoint){
    69. //获取连接点所对应方法的签名信息
    70. Signature signature = joinPoint.getSignature();
    71. System.out.println("LoggerAspect,方法:"+signature.getName()+",异常通知");
    72. }*/
    73. /**
    74. * 在异常通知中若要获取目标对象方法的异常
    75. * 只需要通过AfterThrowing注解的throwing属性
    76. * 就可以将通知方法的某个参数指定为接收目标对象方法出现的异常的参数
    77. */
    78. @AfterThrowing(value = "pointCut()", throwing = "ex")
    79. public void afterThrowingAdviceMethod(JoinPoint joinPoint, Throwable ex){
    80. //获取连接点所对应方法的签名信息
    81. Signature signature = joinPoint.getSignature();
    82. System.out.println("LoggerAspect,方法:"+signature.getName()+",异常:"+ex);
    83. }
    84. //环绕通知
    85. @Around("pointCut()")
    86. //环绕通知的方法的返回值一定要和目标对象方法的返回值一致
    87. public Object aroundAdviceMethod(ProceedingJoinPoint joinPoint){
    88. Object result = null;
    89. try {
    90. System.out.println("环绕通知-->前置通知");
    91. //表示目标对象方法的执行
    92. result = joinPoint.proceed();
    93. System.out.println("环绕通知-->返回通知");
    94. } catch (Throwable throwable) {
    95. throwable.printStackTrace();
    96. System.out.println("环绕通知-->异常通知");
    97. } finally {
    98. System.out.println("环绕通知-->后置通知");
    99. }
    100. return result;
    101. }
    102. }

     

    测试:

    1. /**
    2. public class AOPByAnnotationTest {
    3. @Test
    4. public void testAOPByAnnotation(){
    5. //获取IOC容器
    6. ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml");
    7. //获取目标对象
    8. // CalculatorImpl calculator = ioc.getBean(CalculatorImpl.class);
    9. //获取代理对象
    10. Calculator calculator = ioc.getBean(Calculator.class);
    11. calculator.div(10, 1);
    12. }
    13. }

     

     二 .切面的优先级

    相同目标方法上同时存在多个切面时,切面的优先级控制切面的 内外嵌套 顺序。
    优先级高的切面:外面
    优先级低的切面:里面
    使用 @Order 注解可以控制切面的优先级:
    @Order( 较小的数 ) :优先级高
    @Order( 较大的数 ) :优先级低

     创建验证功能切面 ValidateAspect

    1. @Component
    2. @Aspect
    3. public class ValidateAspect {
    4. //@Before("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    5. @Before("com.atguigu.spring.aop.annotation.LoggerAspect.pointCut()")
    6. public void beforeMethod(){
    7. System.out.println("ValidateAspect-->前置通知");
    8. }
    9. }
    测试
    1. package com.atguigu.spring.test;
    2. public class AOPByAnnotationTest {
    3. @Test
    4. public void testAOPByAnnotation(){
    5. //获取IOC容器
    6. ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml");
    7. //获取目标对象
    8. // CalculatorImpl calculator = ioc.getBean(CalculatorImpl.class);
    9. //获取代理对象
    10. Calculator calculator = ioc.getBean(Calculator.class);
    11. calculator.div(10, 1);
    12. }
    13. }

    设置优先级@Order(1)

    1. @Component
    2. @Aspect
    3. @Order(1)
    4. public class ValidateAspect {
    5. //@Before("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
    6. @Before("com.atguigu.spring.aop.annotation.LoggerAspect.pointCut()")
    7. public void beforeMethod(){
    8. System.out.println("ValidateAspect-->前置通知");
    9. }
    10. }
    测试;
    1. public class AOPByAnnotationTest {
    2. @Test
    3. public void testAOPByAnnotation(){
    4. //获取IOC容器
    5. ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml");
    6. //获取目标对象
    7. // CalculatorImpl calculator = ioc.getBean(CalculatorImpl.class);
    8. //获取代理对象
    9. Calculator calculator = ioc.getBean(Calculator.class);
    10. calculator.div(10, 1);
    11. }
    12. }

     

     总结:

    切面的优先级
    * 可以通过@Order注解的value属性设置优先级,默认值Integer的最大值
    * @Order注解的value属性值越小,优先级越高

     全部总结:

    /*
     * 1、在切面中,需要通过指定的注解将方法标识为通知方法
     * @Before:前置通知,在目标对象方法执行之前执行
     * @After:后置通知,在目标对象方法的finally字句中执行
     * @AfterReturning:返回通知,在目标对象方法返回值之后执行
     * @AfterThrowing:异常通知,在目标对象方法的catch字句中执行
     *
     *
     * 2、切入点表达式:设置在标识通知的注解的value属性中
     * execution(public int com.atguigu.spring.aop.annotation.CalculatorImpl.add(int, int)
     * execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..)
     * 第一个*表示任意的访问修饰符和返回值类型
     * 第二个*表示类中任意的方法
     * ..表示任意的参数列表
     * 类的地方也可以使用*,表示包下所有的类
     * 3、重用切入点表达式
     * //@Pointcut声明一个公共的切入点表达式
     * @Pointcut("execution(* com.atguigu.spring.aop.annotation.CalculatorImpl.*(..))")
     * public void pointCut(){}
     * 使用方式:@Before("pointCut()")
     *
     * 4、获取连接点的信息
     * 在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息
     * //获取连接点所对应方法的签名信息
     * Signature signature = joinPoint.getSignature();
     * //获取连接点所对应方法的参数
     * Object[] args = joinPoint.getArgs();
     *
     * 5、切面的优先级
     * 可以通过@Order注解的value属性设置优先级,默认值Integer的最大值
     * @Order注解的value属性值越小,优先级越高
     *
     */

  • 相关阅读:
    【SwitchyOmega】SwitchyOmega 安装及使用
    SpringBoot——全局异常处理
    对比CentOS与Ubuntu:选择最适合你的Linux发行版
    STM32H750之FreeRTOS学习--------(五)临界段代码保护
    Java中实现线程等待和唤醒总结
    Baumer工业相机堡盟工业相如何使用BGAPISDK通过两种不同的方法进行图像回调函数的使用(C#)
    通过Windbg动态调试去捕获C++软件异常的完整过程介绍
    信使mRNA甲基化偶联3-甲基胞嘧啶(m3C)|mRNA-m3C
    Hadoop
    感知+平台+应用:忽米打造4款工业智能硬件产品
  • 原文地址:https://blog.csdn.net/m0_59281987/article/details/127723761