Spring知识点总结(四)之SpringAOP基础
1. Spring aop中的基本概念
• 连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。
通俗讲:
层于层之间调用的过程中,目标层中可供调用的方法,就称之为连接点。
• 切入点(Pointcut):匹配连接点的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。
通俗讲:
在连接点的基础上 增加上切入规则 选择出需要进行增强的切入点 这些基于切入规则选出来的连接点 就称之为切入点。
• 切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。在Spring AOP中,切面可以使用基于模式)或者基于@Aspect注解的方式来实现。
通俗讲:
狭义上就是 当spring拦截下切入点后 将这些切入点 交给 处理类 进行功能的增强,这个处理类就称之为切面。
广义上来讲 将spring底层的代理 切入点 和 处理类 加在一起 实现的 对层与层之间调用过程进行增强的机制 称之为切面。
• 通知(Advice):在切面的某个特定的连接点上执行的动作。其中包括了“around”、“before”和“after”等不同类型的通知(通知的类型将在后面部分进行讨论)。许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。
通俗讲:
在spring底层的代理拦截下切入点后,将切入点交给切面类,切面类中就要有处理这些切入点的方法,这些方法就称之为通知(也叫增强 增强方法)。针对于切入点执行的过程,通知还分为不同的类型,分别关注切入点在执行过程中的不同的时机。
• 目标对象(Target Object): 被一个或者多个切面所通知的对象。也被称做被通知(advised)对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个被代理(proxied)对象。
通俗讲:
就是真正希望被访问到的对象。spring底层的动态代理对他进行了代理,具体能不能真的访问到目标对象,或在目标对象真正执行之前和之后是否做一些额外的操作,取决于切面。
2. spring的aop实现过程
a. 导入aop相关开发包
b. 创建一个切面类
c. 定义通知
d. 定义一个连接点
e. 配置切入点
在MyEclipse中导入aop的schema约束文件,以便于在配置文件中可以提示标签。
在其中配置切入点:
f. 定义切面
g. 执行方法,发现切面确实起作用
3. 切入点表达式
a. within表达式
通过类名进行匹配 粗粒度的切入点表达式
within(包名.类名)
则这个类中的所有的方法都会别表达式识别,成为切入点。
在within表达式中可以使用*号匹配符,匹配指定包下所有的类,注意,只匹配当前包,不包括当前包的子孙包。
在within表达式中也可以用*号匹配符,匹配包
在within表达式中也可以用..*号匹配符,匹配指定包下及其子孙包下的所有的类
b. execution()表达式
语法:execution(返回值类型 包名.类名.方法名(参数类型,参数类型…))
例子1:
<aop:pointcut expression=
"execution(void cn.tedu.service.UserServiceImpl.addUser(java.lang.String))" id="pc1"/>
该切入点规则表示,切出指定包下指定类下指定名称指定参数指定返回值的方法。
例子2:
<aop:pointcut expression="execution(* cn.tedu.service.*.query())" id="pc1"/>
该切入点规则表示,切出指定包下所有的类中的query方法,要求无参,但返回值类型不限。
例子3:
<aop:pointcut expression="execution(* cn.tedu.service..*.query())" id="pc1"/>
该切入点规则表示,切出指定包及其子孙包下所有的类中的query方法,要求无参,但返回值类型不限。
例子4:
<aop:pointcut expression="execution(* cn.tedu.service..*.query(int,java.lang.String))" id="pc1"/>
该切入点规则表示,切出指定包及其子孙包下所有的类中的query方法,要求参数为int java.langString类型,但返回值类型不限。
例子5:
<aop:pointcut expression="execution(* cn.tedu.service..*.query(..))" id="pc1"/>
该切入点规则表示,切出指定包及其子孙包下所有的类中的query方法,参数数量及类型不限,返回值类型不限。
例子6:
<aop:pointcut expression="execution(* cn.tedu.service..*.*(..))" id="pc1"/>
该切入点规则表示,切出指定包及其子孙包下所有的类中的任意方法,参数数量及类型不限,返回值类型不限。这种写法等价于within表达式的功能。
4. SpringAOP的原理
Spring会在用户获取对象时,生成目标对象的代理对象,之后根据切入点规则,匹配用户连接点,得到切入点,当切入点被调用时,不会直接去找目标对象,而是通过代理对象拦截之后交由切面类中的指定的通知执行来进行增强。
Spring自动为目标对象生成代理对象,默认情况下,如果目标对象实现过接口,则采用java的动态代理机制,如果目标对象没有实现过接口,则采用cglib动态代理。开发者可以可以在spring中进行配置,要求无论目标对象是否实现过接口,都强制使用cglib动态代理。
5. Spring的五大通知类型
a. 前置通知
在目标方法执行之前执行执行的通知
前置通知方法,可以没有参数,也可以额外接收一个JoinPoint,Spring会自动将该对象传入,代表当前的连接点,通过该对象可以 获取目标对象 和 目标方法相关的信息。
注意,如果接收JoinPoint,必须保证其为方法的第一个参数,否则报错。
b. 环绕通知
在目标方法执行之前和之后都可以执行额外代码的通知。
在环绕通知中必须显式的调用目标方法,目标方法才会执行,这个显式调用时通过ProceedingJoinPoint来实现的,可以在环绕通知中接收一个此类型的形参,spring容器会自动将该对象传入,注意这个参数必须处在环绕通知的第一个形参位置。
**要注意,只有环绕通知可以接收ProceedingJoinPoint,而其他通知只能接收JoinPoint。
环绕通知需要返回返回值,否则真正调用者将拿不到返回值,只能得到一个null。
环绕通知有
控制目标方法是否执行、有控制是否返回值、甚至改变返回值
的能力
环绕通知虽然有这样的能力,但一定要慎用,不是技术上不可行,而是要小心不要破坏了软件分层的“高内聚 低耦合”的目标。
c. 后置通知
在目标方法执行之后执行的通知。
在后置通知中也可以选择性的接收一个JoinPoint来获取连接点的额外信息,但是这个参数必须处在参数列表的第一个。
在后置通知中,还可以通过配置获取返回值
一定要保证JoinPoint处在参数列表的第一位,否则抛异常
d. 异常通知
在目标方法抛出异常时执行的通知
配置方法:
可以配置传入JoinPoint获取目标对象和目标方法相关信息,但必须处在参数列表第一位
另外,还可以配置参数,让异常通知可以接收到目标方法抛出的异常对象
e. 最终通知
是在目标方法执行之后执行的通知。和后置通知不同之处在于,后置通知是在方法正常返回后执行的通知,如果方法没有正常返-例如抛出异常,则后置通知不会执行。而最终通知无论如何都会在目标方法调用过后执行,即使目标方法没有正常的执行完成。另外,后置通知可以通过配置得到返回值,而最终通知无法得到。
配置方式:
最终通知也可以额外接收一个JoinPoint参数,来获取目标对象和目标方法相关信息,但一定要保证必须是第一个参数。
f. 五种通知执行的顺序
i. 在目标方法没有抛出异常的情况下
前置通知
环绕通知的调用目标方法之前的代码
目标方法
环绕通知的调用目标方法之后的代码
后置通知
最终通知
ii. 在目标方法抛出异常的情况下:
前置通知
环绕通知的调用目标方法之前的代码
目标方法 抛出异常 异常通知
最终通知
iii. 如果存在多个切面:
多切面执行时,采用了责任链设计模式。
切面的配置顺序决定了切面的执行顺序,多个切面执行的过程,类似于方法调用的过程,在环绕通知的proceed()执行时,去执行下一个切面或如果没有下一个切面执行目标方法,从而达成了如下的执行过程:
如果目标方法抛出异常:
g. 五种通知的常见使用场景
前置通知 记录日志(方法将被调用)
环绕通知 控制事务 权限控制
后置通知 记录日志(方法已经成功调用)
异常通知 异常处理 控制事务
最终通知 记录日志(方法已经调用,但不一定成功)
6. AOP的注解方式实现
spring也支持注解方式实现AOP,相对于配置文件方式,注解配置更加的轻量级,配置、修改更加方便。
a. 开启AOP的注解配置方式
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
b. 将制定的类标志位一个切面
@Aspect
c. 配置通知 制定切入点规则
前置通知 @Before
环绕通知 @Around
后置通知 @AfterReturning
异常通知 @AfterThrowing
最终通知 @After
**通过注解的配置 等价于 配置文件的配置
d. 如果一个切面中多个通知 重复使用同一个切入点表达式,则可以将该切入点表达式单独定义,后续引用,注意,在当前切面中通过注解定义的切入点只在当前切面中起作用,其他切面看不到。
e. 在后置通知的注解中,也可以额外配置一个returning属性,来指定一个参数名来接收目标方法执行后的返回值
f. 在异常通知的注解中,也可以额外配置一个throwing属性,来指定一个参数名接受目标方法抛出的异常对象
Spring知识点总结(四)之SpringAOP基础的更多相关文章
- Spring知识点总结(四)之SpringAOP基础 - 代理设计模式
1. 分析程序中存在的问题(高内聚,低耦合) 通过springIOC DI) 以及注解的使用,成功解决了在程序中层与层之间出现的耦合的问题,但是在很多地方仍然存在非该层应该实现的 ...
- Spring学习笔记四:SpringAOP的使用
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6776247.html 一:AOP基础概念 (1)通知(增强)Advice 通知,其实就是我们从众多类中提取出 ...
- Spring知识点小结(四)
一.JdbcTemplate(jdbc模版--抽取的工具) web阶段DBUtils: QueryRunner runner = new QueryRunner(dataSource); ...
- spring cloud系列教程第四篇-Eureka基础知识
通过前三篇文章学习,我们搭建好了两个微服务工程.即:order80和payment8001这两个服务.有了这两个基础的框架之后,我们将要开始往里面添加东西了.还记得分布式架构的几个维度吗?我们要通过一 ...
- Java基础知识点(四)
前言:记录Java基础知识点,方便熟悉与掌握. 1.面向对象的"六原则一法则" “六原则一法则”:单一职责原则.开闭原则.依赖倒转原则.里氏替换原则.接口隔离原则.合成聚合复用原则 ...
- Spring知识点复习
Spring知识点复习 一.专业术语 侵入式设计 引入框架,对现有的类的结构有影响,即需要实现或继承某些特定类.如:Struts框架 非侵入式设计 引入框架,对现有的类结构没有影响.如:Hiberna ...
- Spring实战第四章学习笔记————面向切面的Spring
Spring实战第四章学习笔记----面向切面的Spring 什么是面向切面的编程 我们把影响应用多处的功能描述为横切关注点.比如安全就是一个横切关注点,应用中许多方法都会涉及安全规则.而切面可以帮我 ...
- <转>Spring 知识点提炼
Spring 知识点提炼 1. Spring框架的作用 轻量:Spring是轻量级的,基本的版本大小为2MB 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依 ...
- 四、Android学习第四天——JAVA基础回顾(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 四.Android学习第四天——JAVA基础回顾 这才学习Android的 ...
随机推荐
- FZU 2122 ——又见LKity——————【KMP字符串匹配】
Problem 2122 又见LKity Accept: 413 Submit: 1425Time Limit: 1000 mSec Memory Limit : 32768 KB Pr ...
- solidity语言
IDE:Atom 插件:autocomplete-solidity 代码自动补齐 linter-solium,linter-solidity代码检查错误 language-ethereum支持 ...
- node.js分片上传文件
前端 : <html> <head> <title>分片上传文件</title> </head> <body> <div ...
- node.js异步编程解决方案之Promise用法
node.js异步编程解决方案之Promise var dbBase = require('../db/db_base'); var school_info_db = require('../db/s ...
- Angular6路由复用与延迟加载的冲突解决——看看有备无患
结论: 结论放最上面,送给匆匆查资料的你: 同时使用延迟加载 + 路由复用,一定不能使用route.routeConfig.path做key去缓存,否则会死得难看. 经实测(我没有完全去解读源代码 ...
- 自己用到的vim常用命令
一.前言 这里整理的是我在实习期间用到的常用vim命令,特记录如下,以免忘记. 二.vim常用命令 1.vim中的光标移动 shift+6(^):跳到行首(第一个非空格字符)(注:在shell跳到行首 ...
- vue+mock.js+element-ui模拟数据搞定分页
效果如图: 前提是搭好vue前端框架,npm install mockjs引入mock.js 当前页全部代码如下,其他有关element-ui的引入未提到,仅作参考用 <!-- 用户管理 --& ...
- webstorm 配置Vue.js 语法提示
标签属性 v-text v-html v-once v-if v-show v-else v-for v-on v-bind v-model v-ref v-el v-pre v-cloak v-on ...
- Java入门到精通——框架篇之Hadoop概述
一.Hadoop来历 Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明了倒排索引算法,通过加入了Map ...
- (一)svn介绍
项目管理中的版本控制问题 通常软件开发由多人协作开发,如果对代码文件.文档等没有进行版本控制,将会出现很多问题: 备份多个版本,占用磁盘空间大 解决代码冲突困难 容易引发BUG 难于恢复至以前正确版本 ...