Spring AOP(面向方面编程)

AOP是一种编程范式,一般适用于具有横切逻辑的场合,如访问控制、事务管理、性能监测等。旨在通过允许横切关注点的分离,提高模块化。比较流行的框架有Spring AOP 和 AspectJ。

面向方面编程(Aspect-Oriented Programming,AOP)也称为面向切面编程,是软件编程思想发展到一定阶段的产物,虽然是一种新的编程思想,但却不是面向对象编程的替代品,它只是OOP的有益补充和延伸。

面向对象的编程将程序分解为不同层次的对象,通过封装、继承、多态等特性将对象组织成一个整体来完成功能,但在一定场合,也暴露出一些问题。在传统的业务处理代码中,通常会进行日志记录、参数合法性验证、异常处理、事务控制等操作,虽然使用OOP可以通过组合或者继承的方式重用代码,但要实现某些功能(如日志记录),同样的代码仍然会分散到各个方法中。这样。如果要关闭某个功能,或者对其进行修改,就必须要修改所有的相关方法。这不仅会增加开发者的工作量,相应的代码出错率也会提高。

在业务系统中,总有一些散落 、渗透到系统各处且不得不处理的事情,这些穿插在既定业务中的操作就是所谓的“横切逻辑”,也称为切面。怎么样才能不受这些附加要求的干扰,专注于真正的业务逻辑呢?

将这些重复性的代码抽取出来,放在专门的类和方法中处理,这样就便于管理和维护了。即便如此,依然无法实现既定业务和横切逻辑的彻底解耦,因为业务方法中还要保留这些方法的调用代码,当需要增加或者减少横切逻辑的时候,还是要修改业务方法中的调用代码才能实现。我们所希望的是无需编写显式的调用,而是在需要的时候能够“自动”调用所需的功能,这正是AOP所要解决的问题。

AOP采用横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向抽取机制的方式,使用传统的OOP思想是无法办到的,因为OOP只能实现纵向的重用。

面向方面的编程,简单来说就是在不改变原有程序的基础上为代码增加新的功能,对其进行增强处理,其设计思想来源于代理设计模式。下面以图示的方式进行简单的说明,通常情况下调用对象的方法如图1说示:

 

图1:直接调用对象的方法

 

在代理模式中,可为对象设置一个代理对象,代理对象为func()提供一个代理方法,当通过代理对象的func()方法调用源对象的func()方法时,就可在代理方法中添加新的功能,这就是所谓的增强处理。增强的功能既可以插到源对象的 func()方法前面,也可插到其后面。如图2所示

 

在此模式下,就可在原有代码乃至原业务流程都不变的情况下,直接在业务流程汇总切入新代码,增加新功能,这就是所谓的面向切面编程。AOP的使用,使开发人员在编写业务逻辑时可以专注于核心业务,而不是过多地关注其他业务的实现,这不但提高了开发效率,而且增强了代码的可维护性。

OOP将应用程序分解成多个层次的对象,而AOP将程序分解成多个切面。日志、事务、安全验证等这些通用的、散布在系统各处的需要在实现业务逻辑时关注的事情称为“方面”,也可称为“关注点”。如果能将这些方面集中处理,然后在具体运行时,再由容器动态织入这些方面,至少会有以下两个好处:

可以减少方面代码里的错误,处理策略改变时还能做到统一修改。

在编写业务逻辑时可以专心于核心业务。

因此,AOP要做的事情就是从系统中分离出“方面”,然后集中实现,从而独立地编写业务代码和方面代码,在系统运行时,再将方面织入到系统中。

AOP术语

切面(Aspect)

一个关注点的模块化,该关注点可能会横切多个对象。比如方面(日志、事务、安全验证)的实现,如日志切面、事务切面、权限切面等。在实际应用中,通常存放方面实现的普通JAVA类,该类要别AOP容器识别为切面,需要在配置中通过<bean>标记指定。

连接点(JoinPoint)

程序执行中的某个具体的执行点,比如某方法调用的时候或者处理异常的时候,在Spring AOP中,一个连接点总是表示一个方法的执行。如图2中原对象的func()方法就是一个连接点。

切入点(PointCut)

切入点是指切面与程序流程的交叉点,即那些需要处理的连接点,如图3所示。当某个连接点满足预先指定的条件时,AOP框架能够定位到这个连接点,该连接点将被添加增强处理,该连接点也就变成了切入点。通常在程序中,切入点指的是类或者方法名,如某个通知要应用到所有以add开头的方法中,那么所有满足这一规则的方法都是切入点。

通知/增强处理(Advice)

在切面的某个特定的连接点上执行的动作(一段程序代码),是切面的具体实现。以目标方法为参照点,根据放置的位置不同,可以分为前置通知、后置通知、异常通知、环绕通知和最终通知等5种。

许多AOP框架都是以拦截器作通知模型,并维护一个以连接点为中心的拦截器链。Advice直译为“通知”,但这种说法并不确切,在此翻译为“增强处理”便于理解。

目标对象(Target Object)

目标对象是指被一个或者多个切面所通知的对象,也被称为被通知对象。如果AOP框架采用的是动态AOP实现,那么该对象就是一个被代理的对象。这些对象中只包含核心业务逻辑代码,所有日志、事务、安全验证等方面的功能等待AOP容器的织入。

代理对象(Proxy Object)

代理对象是指将通知应用到目标对象后,被动态创建的对象。代理对象的功能相当于目标对象中实现的核心业务逻辑功能加上方面(日志、事务、安全验证)代码实现的功能。

织入(Weaving)

织入是指生成代理对象并将切面内容放入到流程中的过程,即将切面代码插入到目标对象上,从而创建一个新的代理对象的过程。

 

AOP的概念比较生涩难懂,切面可以理解为由增强处理和切入点组成,既包含了横切逻辑的定义,也包含了连接点的定义。面向切面编程主要关心两个问题,即在什么位置执行什么功能。Sping AOP 是负责实施切面的框架,即由SpringAOP 完成织入工作。

 

Spring AOP 通知包括前置通知、返回通知、正常返回通知、异常通知、环绕通知。使用AOP框架时,开发者需要做的主要工作是定义切入点和通知(增强处理),通常采用XML配置文件或注解的方式,配置好切入点和增强的信息后,AOP框架会自动生成AOP代理。

 

posted @ 2020-01-07 09:26  ywwzhy  阅读(483)  评论(0编辑  收藏  举报