为什么使用AOP
AOP最为典型的应用实际就是数据库事务的管控。例如,当我们需要保存一个用户时,可能要连同它的角色信息一并保存到数据库中。于是,可以看到如图所示的一个流程图。
- 这里的用户信息和用户角色信息,我们都可以使用面向对象编程(OOP)进行设计,但是它们在数据库事务中的要求是,要么一起成功,要么一起失败,这样OOP就无能为力了。数据库事务毫无疑问是企业级应用关注的核心问题之一,而使用AOP可以解决这些问题。
- AOP 还可以减少大量重复的工作。在 spring 流行之前,我们可以使用 JDBC 代码实现很多的数据库操作;但是,在我们获取数据库事务连接、事务操控和关闭数据库连接的过程中,都需要使用大量的try … catch…finally…语句去操作,这显然存在大量重复的工作。是否可以替换这些没有必要重复的工作呢? 答案是肯定的, 这里存在着一个默认的流程,如下所述。
默认流程
默认的流程
- 打开数据库连接,然后对其属性进行设置;
- 执行SQL语句;
- 如果没有异常,则提交事务;
- 如果发生异常,则回滚事务;
- 关闭数据库事务连接。
这个流程可以用下图所示的流程图来描述:
- 执行更新SQL的流程(图2-1)
- 事务流程约定的默认实现(图2-2)
从图 2-2 可以看到,关于数据库的打开和关闭以及事务的提交和回滚都有流程默认给你实现。换句话说,你都不需要完成它们,你需要完成的任务是编写 SQL 这一步而己,然后织入流程中。
AOP的术语和流程
Spring AOP是一种基于方法的AOP,它只能应用于方法上。
-
AOP 术语
- 连接点(join point): 对应的是具体被拦截的对象,因为Spring只能支持方法,所以被拦截的对象往往就是指特定的方法;
- 切点(point cut): 有时候,我们的切面不单单应用于单个方法,也可能是多个类的不同方法,这时,可以通过正则式和指示器的规则去定义,从而适配连接点。切点就是提供这样一个功能的概念。
- 通知(advice): 就是按照约定的流程下的方法,分为前置通知(beforeadvice)、后置通知(after advice)、环绕通知( around advice)、 事后返回通知( afterReturning advice) 和异常通知(afterThrowing advice), 它会根据约定织入流程中,需要弄明白它们在流程中的顺序和运行的条件。
- 目标对象(target): 即被代理对象,例如,约定编程中的HelloServiceImpl 实例就是一个目标对象,它被代理了。
- 引入(introduction): 是指引入新的类和其方法,增强现有Bean的功能。
- 织入(weaving): 它是一个通过动态代理技术,为原有服务对象生成代理对象,然后将与切点定义匹配的连接点拦截,并按约定将各类通知织入约定流程的过程。
- 切面(aspect): 是一个可以定义切点、各类通知和引入的内容,Spring AOP将通过它的信息来增强Bean的功能或者将对应的方法织入流程。
上述的描述还是比较抽象的,从下图(3-1)可以知道连接点、通知、织入、目标对象和切面的概念。
-
Spring AOP流程约定(图3-1)
定义接口:
public interface HelloService { public void sayHello (String name) ; }
实现接口:
public class HelloServiceimpl implements Hell oService { @Override public void sayHello (String name) { if (name == null || name.trim() == ””){ throw new RuntimeException ("parameter is null ! ! ") ; } System.out.println(”hello" + name); } }
如下图3-1所示: