面向切面的Spring
来源:互联网 发布:linux 查看mysql 编辑:程序博客网 时间:2024/04/30 13:09
下班了,坐下来学习一会,单身狗狗回去也是无聊。昨天看了一下切面的知识,信息量有点多,脑子还是一片混 沌,就打算再看一遍,不过这次是边整理边看。
主要内容有:
1. 什么是面向切面编程和AOP术语 2. Spring XML 编写切面 3. 使用@aspectJ 编写切面 ## 什么是面向切面编程和AOP术语 ##
软件开发过程中分布于应用中的多处的功能被称为横切关注点,这些关注点与应用的业务逻辑时相分离的,将这些横切关注点和业务逻辑想分离是面向切面编程要解决的。是不是有点晦涩,举个例子是怎么回事呢,比如我们火车票事业部做火车票的业务,其中有个功能是发送邮件,发送邮件这个功能跟火车票的业务逻辑是不相干的,可能其他部门也要发送邮件这个功能,那么发送邮件就是横切关注点,把发送邮件作为一个切面嵌入到火车票业务逻辑中,可以实现分离。是不是有点小明白了,继续。
AOP术语包括:
- 通知:描述切面的作用和什么时候起作用,即什么、何时
- 切点:描述切面作用的范围,即何处
- 切面:通知和切点的集合,即什么、何时、何处
- 连接点:能够插入切面的地方
- 引入:为现有的类添加新方法或属性
- 织入:将切面应用到现有对象来创建代理的过程
那么Spring是如何利用AOP 的呢?是不是也有这个疑问?答案就是Spring的AOP框架 采用一个包裹目标对象的代理类来执行切面的的逻辑,搜噶!遗憾的是Spring只支持方法的连接点,(也就是只能在方法级别插入切面,不能再方法内部插入,书上说的没我说的明白)但是基本上已经够用了。
## Spring XML 编写切面 ##
Spring借助AspectJ的切点表达式语音来定义Spring切面,Spring支持的指示器有:
arg() 限制连接点匹配参数 为 指定类型的执行方法
@args() 限制连接点匹配参数 由 指定注解标注的执行方法
execution() 用于匹配是连接点的执行方法
this() 限制连接点匹配AOP代理的Bean引用 为 指定的类型的类
target() 限制连接点匹配目标对象 为 指定类型的类
@target() 限制连接点匹配目标对象 为 特定的执行对象,这些对象要具备指定的类型的注解
within() 限制连接点匹配 指定的类型
@within() 限制连接点匹配 指定注解标注的类型
annotation 限制匹配 带有指定注解的连接点
举个编写切点的例子(切点是啥,看前面):
execution(com.springinaction.springidol.Instrument.play(…))&&within(com.springinaction.springidol. )
啥意思呢,就是当springidol包下的play()方法执行时,会触发通知,通知是啥,看前面。
其实还有一个bean()指示器,用Bean的ID来表示Bean。比如:
execution(*com.springinaction.springidol.Instrument.play(…)) and !bean(eddie)
啥意思,就是Bean的名字不是eddie的play()方法执行时,会触发通知,eddie的play()方法执行时不会触发通知,就这么简单。
一个POJO类声明为切面有两种方式,一种是在XML中,一种是使用@AspectJ注解。先看第一种。
语法:
定义AOP通知器
定义AOP后置通知
定义AOP after-returning通知
定义AOP after-throwing后置通知
定义AOP环绕通知
定义切面
启用@AspectJ 注解驱动的切面
定义AOP前置通知
顶层的AOP配置元素
为被通知的对象引入额外的借口
定义切点
看上去是不是有点晕,别担心,后面你就都会了。因为Example来了,例子一直让我很惊喜,因为例子的存在大大简化了我们的理解。
我们定义一个观众类:
pacage com.springinaction.springidol;public calss Audience{ public void takeSeats(){ system.out.printlin("the audience is taking their seats.") } public void turnOffCellPhones(){ system.out.printlin("the audience is turning their cellphones.") } public void applaud(){ system.out.printlin("CLAP CLAP CLAP CLAP CLAP CLAP.") } public void demandRefund(){ system.out.printlin("Boo! we want our money back!") }}
然后XML把这个Bean引入
<bean id = "audience" class = "com.springinaction.springidol.Audience" />
下面才是我们的核心,在XML中把这个POJO声明为一个切面。
<aop:config> <aop:aspect ref = "audience"> <aop:before pointcut = "execution(*com.springinaction.springidol.performer.perform(...))" method = "takeSeats" /> <aop:before pointcut = "execution(*com.springinaction.springidol.performer.perform(...))" method = "turnOffCellPhones" /> <aop:after-returning pointcut = "execution(*com.springinaction.springidol.performer.perform(...))" method = "applaud" /> <aop:after-throwing pointcut = "execution(*com.springinaction.springidol.performer.perform(...))" method = "demandRefund" /> </aop:aspect> </aop:config>
或者采用简化的方式:
<aop:config> <aop:aspect ref = "audience"> <aop:pointcut id="performace" expression = "execution(*com.springinaction.springidol.performer.perform(...))" method = "takeSeats" /> <aop:before pointcut-ref ="performace" method = "takeSeats" /> <aop:before pointcut-ref ="performace" method = "turnOffCellPhones" /> <aop:after-returning pointcut-ref ="performace" method = "applaud" /> <aop:after-throwing pointcut-ref ="performace" method = "demandRefund" /> </aop:aspect> </aop:config>
哼,还用得着解释么,是不是全明白了,继续加油↖(^ω^)↗。
声明环绕通知:
假如有个一个POJO
public void watchperformance(ProceedingJiontPoint jointpoint){ try{ system.out.printlin("the audience is taking their seats."); system.out.printlin("the audience is turning their cellphones."); long start = Syetem.currentTimeMillis(); jointpoint.proceed(); long end = System.currentTimeMillis(); system.out.printlin("CLAP CLAP CLAP CLAP CLAP CLAP."); syetem.out.printlin("the perform took"+(end-start)+"milliseconds"); } catch (Throwable t){ system.out.printlin("Boo! we want our money back!"); }
XML如下:
<aop:config> <aop:aspect ref = "audience"> <aop:pointcut id="performace2" expression = "execution(*com.springinaction.springidol.performer.perform(...))" /> <aop:around pointcut-ref ="performace2" method = "watchPerformance()" /> </aop:aspect> </aop:config>
为通知传递一个参数:
加入一个切点有一个参数,那么怎么把这个参数传给通知呢?看下面:
<aop:config> <aop:aspect ref = "audience"> <aop:pointcut id="performace3" expression = "execution(*com.springinaction.springidol.performer.perform(string))" and args (dongfengpo) /> <aop:around pointcut-ref ="performace3" method = "watchPerformance" arg-names = "dongfengpo"/> </aop:aspect> </aop:config>
歌曲东风破 传过去了,嘎嘎。
通过切面引入新功能:
假如为所有的performer 引入一个新功能:
pacage com.springinaction.springidol;public interface Contestant{ void receiveAward(); }
怎么办呢?
<aop:config> <aop:aspect > <aop:declare-parents type-matching = "com.springinaction.springidol.Perfromer+" implent-interface ="pacage com.springinaction.springidol.Contestant" default-impl = "pacage com.springinaction.springidol.GraciousContestant" </aop:aspect> </aop:config>
解释一下,就是 Perfromer接口会实现Contestant接口,具体接口的实现方法是GraciousContestant
使用@aspectJ 编写切面
直接上代码,如何把前面的audience 使用注解声明为一个切面
pacage com.springinaction.springidol;@Aspectpublic calss Audience{ @Pointcut("execution(*com.springinaction.springidol.performer.perform(...))") public void performance(){ } @Before(" performance()") public void takeSeats(){ system.out.printlin("the audience is taking their seats.") } @Before(" performance()") public void turnOffCellPhones(){ system.out.printlin("the audience is turning their cellphones.") } @AfterReturning(" performance()") public void applaud(){ system.out.printlin("CLAP CLAP CLAP CLAP CLAP CLAP.") } @AfterThrowing(" performance()") public void demandRefund(){ system.out.printlin("Boo! we want our money back!") }}
跟之前一样,XML中把audience 注入进来
<bean id = "audience" class = "com.springinaction.springidol.Audience" />
最后要做的是让Spring把 audience应用为一个切面
<aop:aspectj-autoproxy />
这段声明会自动代理一些Bean ,这些Bean与使用@Aspect注解的Bean中用@Pointcut 注解的方法匹配
今天继续:
注解环绕通知,要使用@around注解
@Around("performance()")public void watchperformance(ProceedingJiontPoint jointpoint){ try{ system.out.printlin("the audience is taking their seats."); system.out.printlin("the audience is turning their cellphones."); long start = Syetem.currentTimeMillis(); jointpoint.proceed(); long end = System.currentTimeMillis(); system.out.printlin("CLAP CLAP CLAP CLAP CLAP CLAP."); syetem.out.printlin("the perform took"+(end-start)+"milliseconds"); } catch (Throwable t){ system.out.printlin("Boo! we want our money back!"); }
和之前相比,区别就是POJO使用@Around标注,省去了XML中的配置
- 面向切面的Spring
- 面向切面的spring
- 面向切面的Spring
- 面向切面的Spring
- 面向切面的Spring
- Spring面向切面的编程
- Spring的面向切面AOP
- 面向切面的Spring<一>
- 面向切面的 Spring —— 什么是面向切面编程?
- Spring 第四章 面向切面的Spring
- Spring入门之面向切面的Spring
- 面向切面的 Spring —— 如何注入 AspectJ 切面?
- Spring 的AOP(面向切面编程)
- spring的AOP面向切面编程
- spring 面向切面编程AOP的原理
- 第4章 面向切面的Spring
- Spring面向切面(AOP)的例子
- 关于Spring的AOP面向切面编程
- 网络编程基础(1) : 网路模型简介+同步阻塞实例
- 电子或通信领域当前的主流技术及社会需求调查报告
- Java设计模式之简单工厂模式
- 排序算法(2)-直接插入排序
- MATLAB 读取AVI视频 Unable to locate decompressor to decompress video stream
- 面向切面的Spring
- CSU 1553-Good subsequence(RMQ)
- 前序中序、中序后序二叉树的建立
- c语言摄氏度华氏度转换
- k-近邻算法-python实现
- Java虚拟机 程序计数器
- hdu 1274展开字符串(用栈来实现的)
- hdu1785 You Are All Excellent (极角排序)
- 【Android】手写Android异步加载框架