文章目录

  • 1、AOP是什么
  • 2、AOP中注解的含义
  • 3、Pointcut切入点的语法
  • 4、AOP代码实现

1、AOP是什么

AOP:Aspect Oriented Programming,翻译过来就是大名鼎鼎的“面向切面编程”,它是对面向对象的一种补充和完善。
AOP的使用场景一般有:数据源切换、事务管理、权限控制、日志打印等。根据它的名字我们不难理解,它的实现很像是将我们要实现的代码切入业务实现的逻辑中。它有以下特点:
1、侵入性小,几乎可以不改动原来逻辑的情况下把新的逻辑加入业务。
2、实现方便,使用几个注解就可以实现,使系统更容易扩展。
3、更好的复用代码,比如事务日志打印,简单逻辑适合所有情况。

相关代码请参考: chapter-4-springmvc-sourcecode-analysis
https://gitee.com/leo825/spring-framework-learning-example.git

2、AOP中注解的含义

@Aspect:切面。表示一个横切进业务的一个对象。它里面包含切入点(Pointcut)和Advice(通知)。
@Pointcut:切入点。表示需要切入的位置,比如某些类或者某些方法,也就是先定一个范围。
@Before:Advice(通知)的一种,切入点的方法体执行之前执行。
@Around:Advice(通知)的一种,环绕切入点执行也就是把切入点包裹起来执行。
@After:Advice(通知)的一种,在切入点正常运行结束后执行。
@AfterReturning:Advice(通知)的一种,在切入点正常运行结束后执行,异常则不执行
@AfterThrowing:Advice(通知)的一种,在切入点运行异常时执行。

3、Pointcut切入点的语法

语法规则如下代码中注释所示:

    /*** 1、使用within表达式匹配* 下面示例表示匹配com.leo.controller包下所有的类的方法*/@Pointcut("within(com.leo.controller..*)")public void pointcutWithin(){}/*** 2、this匹配目标指定的方法,此处就是HelloController的方法*/@Pointcut("this(com.leo.controller.HelloController)")public void pointcutThis(){}/*** 3、target匹配实现UserInfoService接口的目标对象*/@Pointcut("target(com.leo.service.UserInfoService)")public void pointcutTarge(){}/*** 4、bean匹配所有以Service结尾的bean里面的方法,* 注意:使用自动注入的时候默认实现类首字母小写为bean的id*/@Pointcut("bean(*ServiceImpl)")public void pointcutBean(){}/*** 5、args匹配第一个入参是String类型的方法*/@Pointcut("args(String, ..)")public void pointcutArgs(){}/*** 6、@annotation匹配是@Controller类型的方法*/@Pointcut("@annotation(org.springframework.stereotype.Controller)")public void pointcutAnnocation(){}/*** 7、@within匹配@Controller注解下的方法,要求注解的@Controller级别为@Retention(RetentionPolicy.CLASS)*/@Pointcut("@within(org.springframework.stereotype.Controller)")public void pointcutWithinAnno(){}/*** 8、@target匹配的是@Controller的类下面的方法,要求注解的@Controller级别为@Retention(RetentionPolicy.RUNTIME)*/@Pointcut("@target(org.springframework.stereotype.Controller)")public void pointcutTargetAnno(){}/*** 9、@args匹配参数中标注为@Sevice的注解的方法*/@Pointcut("@args(org.springframework.stereotype.Service)")public void pointcutArgsAnno(){}/*** 10、使用excution表达式* execution(*  modifier-pattern?           //用于匹配public、private等访问修饰符*  ret-type-pattern            //用于匹配返回值类型,不可省略*  declaring-type-pattern?     //用于匹配包类型*  name-pattern(param-pattern) //用于匹配类中的方法,不可省略*  throws-pattern?             //用于匹配抛出异常的方法* )** 下面的表达式解释为:匹配com.leo.controller.HelloController类中以hello开头的修饰符为public返回类型任意的方法*/@Pointcut(value = "execution(public * com.leo.controller.HelloController.hello*(..))")public void pointCut() {}

需要注意:上面的匹配的类型中支持或(||)与(&&)非(!)运算。

4、AOP代码实现

首先配置pox.xml进行注解jar包的支持

        <!-- aop aspect注解导包--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.9</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.9</version></dependency>

然后在配置文件中启动注解支持,例如我的是myspringmvc-servlet.xml文件,这里需要注意的是注解要跟配置文件在一块,举个例子:如果需要切入Controller的配置就需要在myspringmvc-servlet.xml中添加,如果是切入应用的配置如Service则需要在applicationContext.xml中添加。

    <!-- 开启Aop注解 --><aop:aspectj-autoproxy  proxy-target-class="true"></aop:aspectj-autoproxy>

Aop核心代码如下:

    ThreadLocal<Long> startTime = new ThreadLocal<>();/*** 10、使用excution表达式* execution(*  modifier-pattern?           //用于匹配public、private等访问修饰符*  ret-type-pattern            //用于匹配返回值类型,不可省略*  declaring-type-pattern?     //用于匹配包类型*  name-pattern(param-pattern) //用于匹配类中的方法,不可省略*  throws-pattern?             //用于匹配抛出异常的方法* )** 下面的表达式解释为:匹配com.leo.controller.HelloController类中以hello开头的修饰符为public返回类型任意的方法*/@Pointcut(value = "execution(public * com.leo.controller.HelloController.hello*(..))")public void pointCut() {}/*** 在方法执行之前执行** @param joinPoint*/@Before(value = "pointCut()")public void beforeLog(JoinPoint joinPoint) {System.out.println("进入LogAop的beforeLogger");startTime.set(System.currentTimeMillis());}/*** 在进入类之前执行,然后返回pjp.proceed()之前执行before,再执行方法体,在到after** @param*/@Around(value = "pointCut()")public Object aroundLog(ProceedingJoinPoint pjp) throws Throwable {System.out.println("进入LogAop的aroundLogger");return pjp.proceed();}/*** 在方法执行返回之后执行*/@After(value = "pointCut()")public void afterLog() {System.out.println("进入LogAop的afterLogger");long start = startTime.get();System.out.println("方法体执行耗时:" + (System.currentTimeMillis() - start) + "ms");startTime.remove();}/*** 在返回之后执行* @param o*/@AfterReturning(value = "pointCut()",returning = "o")public void afterRunningLog(Object o){System.out.println("进入LogAop的afterRunningLog");System.out.println(o.getClass());}/*** 在产生异常时执行*/@AfterThrowing(value = "pointCut()")public void afterThrowingLog(){System.out.println("进入LogAop的afterThrowingLog");}

开启debug模式,查看各个标签执行顺序;
1、断点进入@Around位置

2、执行完pjp.proceed()之后,开始进入@Before方法

3、执行完@Before中的方法后进入主方法

4、执行完主方法体,又回到了@Around的返回值

5、然后开始执行@After中内容

6.最后到了@AfterReturning方法体中

所以,正常的执行顺序是:@Around ->@Before->主方法体->@Around中pjp.proceed()->@After->@AfterReturning

如果存下异常那执行顺序是什么呢?以下模拟了一个异常。
1、首先进入了@Around的方法

2、进入了@After的方法

3、最后进入了@AfterThrowing的方法

因此如果异常在Around中pjp.proceed()之前,则执行顺序为:@Around -> @After -> @AfterThrowing

同理,如果异常在Around中pjp.proceed()之后,则执行顺序为@Around ->@Before->主方法体->@Around中pjp.proceed()->@After->@AfterThrowing*

Spring AOP详解一文搞懂@Aspect、@Pointcut、@Before、@Around、@After、@AfterReturning、@AfterThrowing相关推荐

  1. 标准差详解-一文搞懂标准差的含义

    标准差详解-一文搞懂标准差的含义 转载自 样本标准差的意义是什么? 的第一个回答

  2. Spring AOP详解(转载)所需要的包

    上一篇文章中,<Spring Aop详解(转载)>里的代码都可以运行,只是包比较多,中间缺少了几个相应的包,根据报错,几经百度搜索,终于补全了所有包. 截图如下: 在主测试类里面,有人怀疑 ...

  3. Spring AOP详解(http://sishuok.com/forum/posts/list/281.html)

    三6.5  AspectJ切入点语法详解 6.5.1  Spring AOP支持的AspectJ切入点指示符 切入点指示符用来指示切入点表达式目的,,在Spring AOP中目前只有执行方法这一个连接 ...

  4. spring aop详解

    1.前言 spring aop是一个面向切面的编程,在自己第一遍学习的时候,感觉aop没有什么作用,但是真实接触下来,感觉spring aop还是很有用途的,感觉自己之前的想法太年轻了. 2.概念 S ...

  5. python协程详解_彻底搞懂python协程-第一篇(关键词1-4)

    任何复杂的概念或系统都不是凭空出现的,我们完全可以找到它的演化历程,寻根究底终会发现,其都是在一系列并不那么复杂的简单组件上发展演化而来! by 落花僧 本文通过一系列关键概念,逐步递进理解协程. 0 ...

  6. 细说Spring——AOP详解(AOP概览)

    一.对AOP的初印象 首先先给出一段比较专业的术语(来自百度): 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方 式和运行期动态代理实 ...

  7. SpringBoot—集成AOP详解(面向切面编程Aspect)

    关注微信公众号:CodingTechWork,一起学习进步. AOP介绍 AOP概述   AOP是Aspect-Oriented Programming,即为面向(切面)方面编程.在维基百科中的解释: ...

  8. dbcp连接池配置详解_重学MySQL:事务与连接池,一文详解带你搞懂

    拼多多三面惨败,java中间件.数据库与spring框架,答不上... 吊打MySQL:21性能优化实践+学习导图+55面试+笔记+20高频知识点 Mysql事务 事务: 事务指逻辑上的一组操作,组成 ...

  9. ANSI、GBK、Unicode等等iconv转换详解一文搞定

    本文首发于公众号"嵌入式软件实战派",关注后获得更多精品干货. > 网页上的编码 也许你会问,自从有了互联网,全世界都近在咫尺,那么网页上的编码时什么,是怎么做到不同语言文字 ...

最新文章

  1. jq 修改swal的标题_js-jquery-SweetAlert【一】使用
  2. caffe显示特征图
  3. 分布式数据库切分规则介绍
  4. 「后端小伙伴来学前端了」Vue中全局事件总线(GlobalEventBus)原理及探究过程
  5. 「递归」第2集 | 变得了魔术,解得了高数,这届鹅厂程序员有点酷
  6. elasticsearch 6.x (五) 单一文档 API 介绍和使用 update和delete API
  7. 【Git】Git提交代码到GitHub的基本操作流程
  8. 企业之haproxy
  9. float的比较要慎重
  10. Mybatis学习笔记-一级缓存与二级缓存
  11. 开启cdn后无法显示字体图标——CDN服务器跨域问题
  12. 终于理解你的软件 搞那么多年了 (通用权限管理系统组件源码完善了7-8年)
  13. 《21天学通Java(第7版)》——VC程序员的学习笔记1
  14. 网络工程师考试串讲视频教程
  15. css空心三角形_CSS实现空心三角指示箭头
  16. 计算机是uefi启动 不能装win7,UEFI引导GPT安装win7方法
  17. ESXi 6 升级到ESXi 6.5VIB冲突问题
  18. java大写英文字母_输出一个字符串中的大写英文字母数,小写英文字母数以及非英文字母(.java)...
  19. 线程生命周期及六种状态
  20. GTN Yan LeCun 1998 文章中的一步

热门文章

  1. SAP SMW0 上传EXCEL模板遇到的问题
  2. POPUP_TO_CONFIRM_LOSS_OF_DATA
  3. 除了收割票房,内战中的中国喜剧电影到底在拼什么?
  4. Java yield详解_Java 中的 yield 关键字
  5. linux查看telnet进程,SuseLinux上配置Telnet服务,重启xinetd守护进程时的异常
  6. linux pdf转换swf,CENTOS 5   PDF转换为SWF
  7. Python 常用排序Demo|冒、插、快、希等入门算法
  8. 打印 Python 的一切 —— pprint beeprint
  9. Python: 大型数组运算
  10. Python集合list,tuple,dict,set