spring主要内容之AOP
前两篇文章讲了为了简化代码开发和松散耦合,spring分别使用了模板技术和依赖注入技术。这一篇再说下第三种技术,就是面向切面编程,简称AOP。
在编程中,存在着一些分散在系统各处的零散操作,比如日志、事务、安全等。面向切面编程是把这些分散于系统各处的零散的操作摘出来,交给spring框架去处理它们和业务方法的关系,开发人员只需要关注系统主要业务逻辑即可。这样就可以简化代码开发和系统的层次。
AOP涉及到两个基本概念:切点和切面。
首先解释下切点。可以把切点理解为“被切割出来的点”,在代码中体现为一个方法。
假如要在方法M执行前,执行日志方法B;在方法M执行后,执行日志方法A。读这句话的时候,我们明显感觉到,方法M被分离了出来,被凸显了出来。这是因为日志方法B和日志方法A的执行,像是在方法M的前后切割了两刀,把方法M摘了出来。
这里方法M就称为切点,因为它被日志方法B和日志方法A从业务逻辑流中切割了出来了。
再解释下切面。可以把切面理解为“用来切割的刀”,在代码中体现为一个方法。上面的例子中,日志方法B和日志方法A就是两个切面。
一个切面不是仅仅可以用来切割一个点,而是可以用来切割多个点。
那么具体的应该如何操作呢?
在spring的配置文件中,首先要定义切点,用aop:pointcut标签来定义。aop:pointcut标签指定了切点对应的方法。
由于一个切面可以切割多个点,所以aop:pointcut标签定义的是一个切点集合(亦即方法的集合),而不仅仅是一个切点。
然后要定义一个切面,用aop:aspect标签和aop:before、aop:after等标签来定义。
aop:aspect标签是一个父标签,表示切面的集合,其内部包含一组具体的切面,包括前切面、后切面、异常切面等,有集合的概念在里面。这些具体的切面对应的方法都是属于同一个类,这个类在父标签aop:aspect中指定。
aop:brefore、aop:after等标签是子标签,它们指定了具体切面对应的方法。
具体代码如下:
package com.zaoren.aspect; public class EdgeOperation { public void readBook() { System.out.println("read the book you want to buy."); } public void updateList() { System.out.println("update the book list after buying a book"); } }
@RequestMapping(value="user") public class UserController { private UserService uService; @RequestMapping(value="buy",method=RequestMethod.GET) public void buy() { System.out.println("--------->>>buy a book."); // uService.searchBook(); } public UserController(UserService uService){ this.uService = uService; } }
<bean id="edgeOperation" class="com.zaoren.aspect.EdgeOperation"/> <aop:config> <aop:pointcut id="pointcut1" expression="execution(public * com.zaoren.controller.*Controller.*(..))"/> <aop:aspect ref="edgeOperation"> <aop:before method="readBook" pointcut-ref="pointcut1"/> <aop:after method="updateList" pointcut-ref="pointcut1"/> </aop:aspect> </aop:config>
控制台输出为:
另外要注意一点,在抛出异常前,会先执行after切面方法。