跟着柴毛毛学Spring(4)——面向切面编程![这里写图片描述](http://img.blog.csdn.net/20171031111402095)
2016-04-02 15:39
411 查看
面向切面编程简介
1. 什么是面向切面编程?
面向切面编程是Spring的第二大特性,它能将一个函数中非主体但有很必要的代码封装到一个单独的类中,在程序运行的时候再把它们插入到函数中。这样能使程序猿只关注函数的主体功能,而且写出来的代码具有具有较强的可读性,简约明了。2. 面向切面编程的优点
面向切面编程的优点有两个:1. 一个函数中所有额外的功能都被封装在一个类中,而不是分散在函数的各处。
2. 由于将非主体功能的代码转移到其他类中,因此函数的代码将更佳简洁。
3. Spring的面向切面编程特点
目前面向切面(AOP)市场的三足鼎立格局是这样的:- AspectJ
- JBoss Aspect
- Spring Aspect
Spring Aspect借鉴AspectJ。
所谓面向切面,前面已经介绍过,就是将函数的一部分代码抽取出来,封装到一个类中,然后在某一时刻将其插入到程序中去。
AOP世界中,将切面插入的到程序中的时机有以下三种:
1. 编译时插入
2. 类被加载的时候插入
3. 程序运行时被插入
Spring是在程序运行期间将切面插入到相关函数中去的。
此外,在编译时插入需要特殊的编译器,在类加载的时候插入需要特殊的类加载器,而在运行时插入不需要额外的软件支持。
开始使用
假设现在有一个函数,用来查询数据库中名字为name的Person对象:public String queryPersons(String name){ //查询的具体操作…… //此处省略100行代码…… }
我们需要在查询开始前判断name是否为空,在查询结束后记录操作日志,在查询发生异常时记录异常日志。
在过去,我们把这些代码都直接写在这个函数中,这样会导致这个函数很长,可读性很差。下面我们使用面向切面编程的思想解决这个问题。
1. 定义切面代码
首先需要将这个函数中额外的功能封装到一个类中,这个类就是一个普通类,功能封装在函数中:class PersonAspect(){ /** * 判断参数是否为空 */ public void verifyNull(String name){ //判断参数是否为空 } /** * 记录操作日志 */ public void logInfo(){ } /** * 记录异常日志 */ public void logError(){ } }
2. 将切面声明为bean
在Spring的配置文件中添加bean的声明:<bean id="personAspect" class="com.njupt.PersonAspect"> </bean>
或者直接在PersonAspect类上使用@Componet标注:
@Componet("personAspect")
class PersonAspect(){ /** * 判断参数是否为空 */ public void verifyNull(String name){ //判断参数是否为空 } /** * 记录操作日志 */ public void logInfo(){ } /** * 记录异常日志 */ public void logError(){ } }
3. 声明通知
定义好了额外的功能之后,接下来我们需要告诉Spring,这些功能需要在何时添加到哪个函数的什么位置,因此我们需要在Spring的配置文件中作如下声明:<aop:config> <aop:aspect ref="personAspect"> <!-- 在queryPersons函数执行之前先运行函数verifyNull --> <aop:before pointcut="excution(* com.njupt.Person.queryPersons(..))" method="verifyNull" /> <!-- 在queryPersons函数执行之后再运行函数logInfo --> <aop:after-returning pointcut="excution(* com.njupt.Person.queryPersons(..))" method="logInfo" /> <!-- 在queryPersons函数发生异常时运行函数logError --> <aop:throwing pointcut="excution(* com.njupt.Person.queryPersons(..))" method="logError" /> </aop:config>
到此为止,Spring AOP已经可以运行了!
4. 声明环绕通知
在上述示例中,函数前插入一段代码,函数后插入一段代码,函数异常时插入一段代码,这些代码块都是独立的,无法共享数据。如果需要实现函数前后代码块的数据共享,那就要使用环绕通知。说来也很简单,首先需要在PersonAspect类中加上一个参数为ProceedingJoinPoint的函数,如下所示:
@Componet("personAspect") class PersonAspect(){ /** * 判断参数是否为空 */ public void verifyNull(String name){ //判断参数是否为空 } /** * 记录操作日志 */ public void logInfo(){ } /** * 记录异常日志 */ public void logError(){ } /** * 环绕通知 */ public void xxx(ProceedingJoinPoint joinPoint){ int num = 0; //在函数前执行一些功能,修改num参数 //执行函数 joinPoint.proceed(); //在函数后处理num num++; //…… } }
然后在配置文件中把这个函数声明为环绕通知即可:
<aop:config> <aop:aspect ref="personAspect"> <!-- 在queryPersons函数执行之前先运行函数verifyNull --> <aop:before pointcut="excution(* com.njupt.Person.queryPersons(..))" method="verifyNull" /> <!-- 在queryPersons函数执行之后再运行函数logInfo --> <aop:after-returning pointcut="excution(* com.njupt.Person.queryPersons(..))" method="logInfo" /> <!-- 在queryPersons函数发生异常时运行函数logError --> <aop:throwing pointcut="excution(* com.njupt.Person.queryPersons(..))" method="logError" /> <!-- 环绕通知 --> <aop:around pointcut="excution(* com.njupt.Person.queryPersons(..))" method="xxx()" /> </aop:aspect> </aop:config>
到此为止,Spring的AOP介绍完毕,下面介绍如何使用注解取代XML。
使用注解代替XML
1. 注解切面
首先需要在切面类上加上注解@Aspect,告诉Spring这个类是个切面类;其次需要在切面类中创建一个函数,用于定义切点。该函数的名字即为切点名,函数返回值和参数均为空。
@Aspect class PersonAspect(){ /** * 定义切点 */ @Pointcut("excution(* com.njupt.Person.queryPersons(..))") public void personAspect(){ } /** * 判断参数是否为空 */ @Before("personAspect()") public void verifyNull(String name){ //判断参数是否为空 } /** * 记录操作日志 */ @AfterReturning("personAspect()") public void logInfo(){ } /** * 记录异常日志 */ @AfterThrowing("personAspect()") public void logError(){ } /** * 环绕通知 */ @Around("personAspect()") public void xxx(ProceedingJoinPoint joinPoint){ int num = 0; //在函数前执行一些功能,修改num参数 //执行函数 joinPoint.proceed(); //在函数后处理num num++; //…… } }
相关文章推荐
- 计算机网络最常用命令---网络安全必杀技
- Java联网技术之一TCP
- 网络叹号 win10 猎豹WIFI 网络连接失败
- Apache 的 httpd.conf 详解(很实用)
- IP TCP UDP 报文格式
- 神经网络-激活函数-面面观(Activation Function)
- 网络:请求本地服务器做法(socket)
- http协议请求方法和状态码
- 网络营销包括什么?
- u-boot网络启动分析(一) 网络初窥
- 网络营销分类小说
- 理解LSTM 网络Understanding LSTM Networks
- 以模块化视角看卷积神经网络Conv Nets: A Modular Perspective
- Android HTTP请求方式:HttpClient
- Android HTTP请求方式:HttpURLConnection
- IP地址从头说起
- Android Http请求头与响应头的学习
- 易语言和VBS发送http请求 自动预约MZD记念馆团体票 分析第2步自动登陆预约carles抓包
- 初步实现网络socket编程
- HttpClient and HttpURLConnection——Android(一)