AOP:面向切面编程【底层使用动态代理实现】,就是在运行期间动态的将某段代码切入到方法的指定位置进行运行的编程方式

基本使用

  1. 使用AOP功能需要引入spring的aop以及aspects相关包

    1. <dependency>
    2. <groupId>org.springframework</groupId>
    3. <artifactId>spring-context</artifactId>
    4. <version>5.0.6.RELEASE</version>
    5. </dependency>
    6.  
    7. <dependency>
    8. <groupId>org.springframework</groupId>
    9. <artifactId>spring-aspects</artifactId>
    10. <version>5.0.6.RELEASE</version>
    11. </dependency> 
  2. 定义逻辑类
    1. public class TestService {
    2. public int service(int i, int j){
    3. System.out.println(".........service........");
    4. return i/j;
    5. }
    6. }
  3. 定义切面类
    1. @Aspect//声明该类是切面类
    2. public class MyAspectJ {
    3.  
    4. /**
    5. * @Before
    6. * 前置通知:在目标方法(service)运行之前运行
    7. */
    8. @Before("execution(public int com.enjoy.study.cap13.TestService.service(int,int))")
    9. public void logStart(){
    10. System.out.println("@Before目标方法执行前");
    11. }
    12.  
    13. /**
    14. * @After
    15. * 后置通知:在目标方法(service)运行结束之后运行,无论正常或异常结束
    16. */
    17. @After("execution(public int com.enjoy.study.cap13.TestService.service(int,int))")
    18. public void logEnd(){
    19. System.out.println("@After目标方法执行后");
    20. }
    21.  
    22. /**
    23. * @AfterReturning
    24. * 返回通知:在目标方法(service)正常返回之后运行
    25. */
    26. @AfterReturning("execution(public int com.enjoy.study.cap13.TestService.service(int,int))")
    27. public void logReturn() {
    28. System.out.println("@AfterReturning目标方法执行后返回");
    29.  
    30. }
    31.  
    32. /**
    33. * @AfterThrowing
    34. * 异常通知:在目标方法(service)出现异常后运行
    35. */
    36. @AfterThrowing("execution(public int com.enjoy.study.cap13.TestService.service(int,int))")
    37. public void logThrowing(){
    38. System.out.println("@AfterThrowing目标方法执行出现异常");
    39. }
    40.  
    41. /**
    42. * @Around
    43. * 环绕通知:动态代理,手动执行目标方法运行joinPoint.procced(),最底层通知,手动指定执行目标方法,
    44. * 执行之前相当于前置通知, 执行之后相当于返回通知,其实就是通过反射执行目标对象的连接点处的方法
    45. * @param joinPoint : 用于环绕通知,通过procced()来执行目标方法
    46. * @return
    47. * @throws Throwable
    48. */
    49. @Around("execution(public int com.enjoy.study.cap13.TestService.service(int,int))")
    50. public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    51. System.out.println("@Around目标方法执行前...........");
    52. Object object = joinPoint.proceed();
    53. System.out.println("@Around目标方法执行后...........");
    54. return object;
    55. }
    56. }
  4. 配置类
    1. @Configuration
    2. @EnableAspectJAutoProxy//用于开启spring注解的AOP模式,使得ioc容器可以辨别Aspect类
    3. public class AopMainConfig {
    4. @Bean
    5. public MyAspectJ myAspectJ(){
    6. return new MyAspectJ();
    7. }
    8.  
    9. @Bean
    10. public TestService testService(){
    11. return new TestService();
    12. }
    13. }
  5. 测试

    1. public class TestAspectJ {
    2. @Test
    3. public void testM(){
    4. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopMainConfig.class);
    5. TestService service = context.getBean(TestService.class);
    6. int result = service.service(4, 2);
    7. System.out.println("result = " + result);
    8. }
    9. } 
  6. 结果
    1. @Around目标方法执行前...........
    2. @Before目标方法执行前
    3. .........service........
    4. @Around目标方法执行后...........
    5. @After目标方法执行后
    6. @AfterReturning目标方法执行后返回
    7. result = 2  

知识点

  • execution:用于匹配方法执行的连接点
  • ProceedingJoinPoint:应用于环绕通知,使用proceed()执行目标方法
  • @Aspect:声明当前类是切面类
  • @EnableAspectJAutoProxy:在配置类上使用该注解开启Spring基于注解的AOP模式,使得Spring的IOC容器可以识别哪个bean是Aspect切面bean  

优化

对于上面的切面类,每个通知的execution都一样,是冗余的,导致重复写了多次,可以抽取公共切入方法

  1. @Pointcut("execution(public int com.enjoy.study.cap13.TestService.service(int,int))")
  2. public void pointCut(){}

本类可以直接引用,其他类可以通过路径+方法引用

  1. @Aspect
  2. public class MyAspectJ {
  3.  
  4. @Pointcut("execution(public int com.enjoy.study.cap13.TestService.service(int,int))")
  5. public void pointCut(){}
  6. /**
  7. * @Before
  8. * 前置通知:在目标方法(service)运行之前运行
  9. */
  10. @Before("pointCut()")
  11. public void logStart(){
  12. System.out.println("@Before目标方法执行前");
  13. }
  14.  
  15. /**
  16. * @After
  17. * 后置通知:在目标方法(service)运行结束之后运行,无论正常或异常结束
  18. */
  19. @After("com.enjoy.study.cap13.MyAspectJ.pointCut()")
  20. public void logEnd(){
  21. System.out.println("@After目标方法执行后");
  22. }
  23.  
  24. /**
  25. * @AfterReturning
  26. * 返回通知:在目标方法(service)正常返回之后运行
  27. */
  28. @AfterReturning("pointCut()")
  29. public void logReturn() {
  30. System.out.println("@AfterReturning目标方法执行后返回");
  31.  
  32. }
  33.  
  34. /**
  35. * @AfterThrowing
  36. * 异常通知:在目标方法(service)出现异常后运行
  37. */
  38. @AfterThrowing("pointCut()")
  39. public void logThrowing(){
  40. System.out.println("@AfterThrowing目标方法执行出现异常");
  41. }
  42.  
  43. /**
  44. * @Around
  45. * 环绕通知:动态代理,手动执行目标方法运行joinPoint.procced(),最底层通知,手动指定执行目标方法,
  46. * 执行之前相当于前置通知, 执行之后相当于返回通知,其实就是通过反射执行目标对象的连接点处的方法
  47. * @param joinPoint : 用于环绕通知,通过procced()来执行目标方法
  48. * @return
  49. * @throws Throwable
  50. */
  51. @Around("pointCut()")
  52. public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
  53. System.out.println("@Around目标方法执行前...........");
  54. Object object = joinPoint.proceed();
  55. System.out.println("@Around目标方法执行后...........");
  56. return object;
  57. }
  58. }

我们还可以在切面类中得到方法名、方法的参数、结果、异常等信息

  1. @Aspect
  2. public class MyAspectJ {
  3.  
  4. @Pointcut("execution(public int com.enjoy.study.cap13.TestService.service(int,int))")
  5. public void pointCut(){}
  6.  
  7. /**
  8. * @Before
  9. * 前置通知:在目标方法(service)运行之前运行
  10. * @param joinPoint:应用于每个通知
  11. */
  12. @Before(value = "pointCut()")
  13. public void logStart(JoinPoint joinPoint){
  14. System.out.println("@Before目标方法执行前,方法名:"+joinPoint.getSignature().getName()+
  15. "方法参数:"+ Arrays.asList(joinPoint.getArgs()));
  16. }
  17.  
  18. /**
  19. * @After
  20. * 后置通知:在目标方法(service)运行结束之后运行,无论正常或异常结束
  21. */
  22. @After("com.enjoy.study.cap13.MyAspectJ.pointCut()")
  23. public void logEnd(){
  24. System.out.println("@After目标方法执行后");
  25. }
  26.  
  27. /**
  28. * @AfterReturning
  29. * 返回通知:在目标方法(service)正常返回之后运行
  30. */
  31. @AfterReturning(value = "pointCut()",returning = "result")
  32. public void logReturn(Object result) {
  33. System.out.println("@AfterReturning目标方法执行后返回结果:"+result);
  34.  
  35. }
  36.  
  37. /**
  38. * @AfterThrowing
  39. * 异常通知:在目标方法(service)出现异常后运行
  40. */
  41. @AfterThrowing(value = "pointCut()",throwing = "ex")
  42. public void logThrowing(Exception ex){
  43. System.out.println("@AfterThrowing目标方法执行出现异常信息:"+ex);
  44. }
  45.  
  46. /**
  47. * @Around
  48. * 环绕通知:动态代理,手动执行目标方法运行joinPoint.procced(),最底层通知,手动指定执行目标方法,
  49. * 执行之前相当于前置通知, 执行之后相当于返回通知,其实就是通过反射执行目标对象的连接点处的方法
  50. * @param joinPoint : 用于环绕通知,通过procced()来执行目标方法
  51. * @return
  52. * @throws Throwable
  53. */
  54. @Around("pointCut()")
  55. public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
  56. System.out.println("@Around目标方法执行前...........");
  57. Object object = joinPoint.proceed();
  58. System.out.println("@Around目标方法执行后...........");
  59. return object;
  60. }
  61. }

结果

  1. @Around目标方法执行前...........
  2. @Before目标方法执行前,方法名:service方法参数:[4, 2]
  3. .........service........
  4. @Around目标方法执行后...........
  5. @After目标方法执行后
  6. @AfterReturning目标方法执行后返回结果:2
  7. result = 2

如果有异常会打印异常信息,例如将i/j中的j设置为0

  1. @AfterThrowing目标方法执行出现异常信息:java.lang.ArithmeticException: / by zero

  

spring(六):spring中AOP的基本使用的更多相关文章

  1. Spring中AOP实现

    1.什么是SpringAOP 什么是aop:Aspect Oriented Programming的缩写,面向切面编程,通过预编译和动态代理实现程序功能的 统一维护的一种技术 主要功能:日志记录,性能 ...

  2. Spring中AOP原理,源码学习笔记

    一.AOP(面向切面编程):通过预编译和运行期动态代理的方式在不改变代码的情况下给程序动态的添加一些功能.利用AOP可以对应用程序的各个部分进行隔离,在Spring中AOP主要用来分离业务逻辑和系统级 ...

  3. spring Aop中aop:advisor 与 aop:aspect的区别

    转载:http://blog.csdn.net/u011710466/article/details/52888277 在spring的配置中,会用到这两个标签.那么他们的区别是什么呢?       ...

  4. 关于Spring中AOP的理解

    AOP简介[理解][重点] 1.AOP(Aspect Oriented Programing)面向切面/方面编程 2.AOP隶属软件工程的范畴,指导开发人员如何制作开发软件,进行结构设计 3.AOP联 ...

  5. Spring中AOP简介与切面编程的使用

    Spring中AOP简介与使用 什么是AOP? Aspect Oriented Programming(AOP),多译作 "面向切面编程",也就是说,对一段程序,从侧面插入,进行操 ...

  6. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

  7. Spring 中aop切面注解实现

    spring中aop的注解实现方式简单实例   上篇中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了. 注解方式实现aop我们 ...

  8. Spring中AOP相关源码解析

    前言 在Spring中AOP是我们使用的非常频繁的一个特性.通过AOP我们可以补足一些面向对象编程中不足或难以实现的部分. AOP 前置理论 首先在学习源码之前我们需要了解关于AOP的相关概念如切点切 ...

  9. 六、Spring之初步认识AOP

    Spring之初步认识AOP [1]AOP概览 什么是AOP?(来自百度) ​ 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行 ...

随机推荐

  1. 洛谷 P2783 有机化学之神偶尔会做作弊(Tarjan,LCA)

    题目背景 LS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. “第1354题怎么做”<--手语 他问道 ...

  2. JS基础入门篇(七)—运算符

    1.算术运算符 1.算术运算符 算术运算符:+ ,- ,* ,/ ,%(取余) ,++ ,-- . 重点:++和--前置和后置的区别. 1.1 前置 ++ 和 后置 ++ 前置++:先自增值,再使用值 ...

  3. RAC搭建---自己做

    一.本地磁盘是指你本身加上去的磁盘,只能本机使用的.共享磁盘是指可以多台机器同时读取写入.你做RAC就要用到共享存储: 二.ORC分区一般1G*3  数据分区5G*3  ,FRA分区一般5G*3  这 ...

  4. php-redis 使用命令

    PHP 使用redis 一些命令参考:https://www.jianshu.com/p/68b7114a1d70

  5. darknet-yolov3使用opencv3.4.8时,undefined reference 'imshow()'、'waitKey()'、'nameWindows()'

    解决办法:暴力卸载 卸载办法:进入到opencv3.4.8的安装目录下:make uninstall 然后重新安装了其他版本的,立马编译通过了.

  6. c#代码规则,C#程序中元素的命名规范

    俩种命名方法 1.Pascal 命名法,第一个字母大写其它字母小写Userid 2.Camel命名法,所有单第一方写大写,其它小写,骆峰命名法,userId C#程序中元素的命名规范项目名:公司名.项 ...

  7. 【HDOJ6665】Calabash and Landlord(dfs)

    题意:二维平面上有两个框,问平面被分成了几个部分 x,y<=1e9 思路:分类讨论可以 但数据范围实在太小了,离散化以后随便dfs一下 #include<bits/stdc++.h> ...

  8. 元素隐藏visibility:hidden与元素消失display:none的区别

    visibility属性用来确定元素是显示还是隐藏的,这用visibility="visible|hidden"来表示(visible表示显示,hidden表示隐藏). 当visi ...

  9. 破解 MyEclipse For Spring 的步骤

    破解 MyEclipse For Spring 的步骤: 1.关闭myeclipse: 2.运行破解工具,写上UserCode,最好是 8 位以上, 3.注意选择 myeclipse 的版本,我提供的 ...

  10. win10半夜自动开机的问题分析

    win10半夜自动开机的系统日志: 解决方法一: 1.根据日志判断自动唤醒后,windows更新了时间和代理 服务管理器中,关闭windows update, 但是半夜还会自动开 再关闭服务管理器的w ...