Spring AOP学习笔记

     Ⅰ。Aspect Oriented Programming(AOP)是近年来计算机技术中比较热门的话题之一。其发展历史从学术领域和研发机构的运用开始,目前流行的Spring应用程序框架将AOP思想融入了整个框架的设计开发与应用当中。使用Spring框架固然给我们的编程带来了好处与便利,但是同时存在着一个问题,对于初学者来说,所谓的“控制反转”,不是一个能够望文生义的好名称,“依赖注入”也是一样,也正是因为这样,不少初学者很难在短时间内理解和掌握这些名字和他们的用法,而要使用AOP的功能也需要理解AOP,也比较难。基于以上原因,我们就会想到,能否简单地将Spring框架中运用到的优秀的理念,巧妙的运用到我们需要使用的地方,而又绕过不容易上手的Spring框架,做到一举两得呢?本文就将围绕着上述提出的问题给出作者的看法和观点。 

   AOP实际是GoF四人组设计模式的一种扩展,设计模式所追求的是降低代码之间的耦合度,增加程序的灵活性和可重用性,AOP实际上就是设计模式所追求的目标的一种实现。所谓的分离关注就是将某一通用的需求功能从不相关的类之中分离出来;同时,能够使得很多类共享一个行为,一旦行为发生变化,不必修改很多类,只要修改这个行为就可以。AOP就是这种实现分散关注的编程方法,它将“关注”封装在“方面”中。面向对象的编程(OOP)方法是在面向过程的编程方法基础上进行的改进,而面向方面编程(AOP)方法又是在面向对象编程(OOP)方法的基础上进行改进而来的一种创新的软件开发方法。AOP和OOP虽然在字面上十分相似,但是却是面向不同领域的两种设计思想。OOP(面向对象编程)针对问题领域中以及业务处理过程中存在的实体及其属性和操作进行抽象和封装,面向对象的核心概念是纵向结构的,其目的是获得更加清晰高效的逻辑单元划分;而AOP则是针对业务处理过程中的切面进行提取,例如,某一个操作在各个模块中都有涉及,这个操作就可以看成“横切”存在于系统当中。在许多情况下,这些操作都是与业务逻辑相关性不强或者不属于逻辑操作的必须部分,而面向对象的方法很难对这种情况做出处理。AOP则将这些操作与业务逻辑分离,使程序员在编写程序时可以专注于业务逻辑的处理,而利用AOP将贯穿于各个模块间的横切关注点自动耦合进来。AOP所面对的是处理过程中的某个步骤或阶段,对不同的阶段领域加以隔离,已获得逻辑过程中各部分之间低耦合性的隔离效果,其与面向方面编程在目标上有着本质的差异。AOP的核心思想就是将应用程序中的业务逻辑处理部分同对其提供支持的通用服务,即所谓的“横切关注点”进行分离,这些“横切关注点”贯穿了程序中的多个纵向模块的需求。使用AOP机制进行开发,首先要对方面进行了解,将需求分解成一般关注点和横切关注点,即将核心模块级的关注点和系统级的横切关注点分离;然后各自独立的实现这些关注点;最后用工具将业务逻辑代码和横切关注点代码编织到一起,形成最终的程序。通过面向方面的编程可以减少编码时间和重复。

     Ⅱ。AOP常用术语

      Aspect 切面:它是横跨多个核心逻辑的功能,或者称之为系统关注点,例如日志记录、安全检查、事务管理等。以前我们在一个组的每一个方法重复编写这些代码。现在我们将这些散落的代码集中起来,放在一个模块中,这个模块(例如,日志记录)就中一个切面。

     Joinpoint 连接点:连接点主是定义在应用程序的何处插入切面的执行,最容易想到就是一个方法调用时,或者在访问一个字段时,或者在抛出异常时。

     Pointcut 切入点:切入点就是一组连接点的集合。例如,一个切面需要在调用每个以query开头的方法时执行,就可以用正则表达式(.*query.*)或通配符(query*)来表达这一组的连接点,我们将之称为切入点。

     Advice 增强:在特定连接点上执行的动作,执行这个动作就相当于对原始对象的功能做了增强。

     Introduction 引介:为一个已有的java对象动态增加新的接口。这个功能看起来有点玄乎,实际也是AOP的一种功能。

     Weaving 织入:将切面组织到程序的执行流程中。

     Interceptor 拦截器:如何实现增强的一种方式。

     Taget Object 目标对象:真正执行核心逻辑的对象。

     AOP Proxy 代理:AOP代理就是客户端持有的引用。由于AOP代理实现了与目标对象同样的接口,因此客户端感觉不出这两者的区别,但是却获取增强的额外功能。

     Ⅲ。在Spring装配AOP

     Spring大力提倡使用依赖注入的方式来装配Bean,对于AOP也不例外,依赖注入仍是极具杀伤力的武器。Spring提供了ProxyFactory来实现AOP的装配,免去了以编程方式生成AOP代理对象的繁琐步骤,这也是Spring AOP的设计目标之一。Spring 常用的Advice如下①MethodBeforeAdvice:在方法执行前开开始增强。②AfterReturningAdvice:在一个方法执行完毕后增强。③ThrowsAdvice:在一个方法抛出异常时增强。④MethodInterceptor:在一个方法增强前后增强。下面这个是学习的例子,可以供大家学习参考:            

UserDao负责访问数据库,这里使用Map来模拟数据库。    

UserService定义了用户管理的接口中,它仅有两个方法。  

UserServiceImpl则实现了UserService接口中,它需要注入一个UserDao来完成业务方法。

 

 

先创建一个LoginMethodBeforeAdvice,用于记录所有login()方法的调用。记录用户尝试登录的信息。

 

 用LoginAfterReturningAdvice用户记录已经成功的用户。

如果用户登录失败,login方法将会抛出异常,因此,LoginThrowsAdvice用于记录登录失败的情况。

有了目标Bean和Advice后,就可以编写config.xml配置文件,将其在Spring的IoC容器中装配起来。

编写测试类Main.class来测试我们在Spring的IoC容器中配置的AOP

运行测试结果,可以看到如下输出:

 

如果正常返回,则ThrowsAdvice将不会被执行,因为没有异常抛出,自然不会引发ThrowsAdvice执行;如果方法抛出了异常,则ThrowsAdvice将被执行,而AfterReturningAdvice就不能被执行,因为当异常抛出时,方法是没有任何返回值 的,自然无法执行AfterReturningAdvice。

 

例2:编写Advisor的例子

是在上一个工程扩展的例子,演示如何使用Advisor来截获指定的方法。

 

新增CreateAfterReturningAdvice.class,用于对create()方法增强。

LoginMethodBeforeAdvice不变。

 下面需要做的就是将Advice封装为Advisor,需要用NameMatchMethodPointcutAdvisor来定义LoginMethodBeforeAdvice,应当仅仅作用于login()方法,然后使用RegexpMethodPointcutAdvisor来定义CreateAfterReturningAdvice应当作用于所有以create开头的方法。最后将这两个Advisor装配起来。config.xml如下:

为了验证这两个Advisor是否对特定的方法进行了增强,我们在main()方法中调用UserService的不同方法。

运行结果如下:

可见,create()方法和login()方法分别被createAfterAdvisor和loginBeforeAdvisor增强,这校们就实现了特定的方法的增强,而不是对所有方法都增强。

你可能感兴趣的:(设计模式,spring,AOP,编程,oop)