在软件开发的过程中,有些行为对于大多数应用都是通用的,最常见的通用行为就是事务管理。事务管理是实际数据库应用中必不可少的功能,不能算是真正的业务逻辑,它是为了保证数据的安全性,与具体的业务逻辑并无关系。将类似于事务管理这样的通用行为与真正的业务逻辑行为分离开来,使得开发人员开发的时候,无需关注这些通用行为,只需关注核心的业务逻辑,正是 AOP 所需要解决的问题。
与大多数技术一样,AOP 有自己的术语,想要更好的理解 AOP,我们首先要先理解一些基本的术语。这里,讲述几个最常用到的。
连接点(Joinpoint)
程序执行过程中的某个特定的点,或者说特定的时候。比如类初始化的时候,方法调用的时候,异常处理的时候,在 Spring AOP 中,一个连接点总是表示一个方法执行的时候。
连接点的这个“点”字,不能以数学思维来理解,这个“点”我们可以理解为一个程序单元,里面包含着一段程序,是有代码的。从概念上讲,就是某件事发生的时候,或者是某段代码执行的时候。再简言之,连接点就是一段可执行的程序代码。
切点(Pointcut)
切点是用来匹配定位连接点的。
通常,程序中总会有很多很多的连接点,需要的不需要的都有。我们要做的,就是利用切点,定义一些规则,匹配出我们需要的连接点。
理解切点,可以类比正则表达式。
通知(Advice)
在 Spring AOP 中,有前置通知、后置通知、异常通知、最终通知、环绕通知 5 种。
通知包含两层内容,一是“什么事情”,二是“什么时间”。通俗讲,“什么事情”就是一段程序代码,代码需要完成的一些工作;“什么时间”就是连接点代码执行前或者执行后。再简言之,通知要做的事情,就是在连接点代码执行到某个特定的时候,执行自己的代码。拿 Spring AOP 来讲,通知的代码在连接点代码执行前先执行,就是前置通知;在连接点代码执行之后再执行,就是后置通知;在之前、之后都要执行,就是环绕通知;在抛出异常的时候执行,就是异常通知;在连接点代码执行完以后,忽略其返回结果,也不管它有没有抛出异常,都要执行通知的代码,这就是最终通知。
理解通知,可以类比现实生活中的消息通知。
切面(Aspect)
切面是通知和切点的结合。
其实,光有通知是完成不了任何事情的。举个例子,我写了一份通知“今天下班后,公司技术部全体员工聚餐”,通知的时间是“今天下班后”,通知的事情是“聚餐”。这件事情到时候能完成吗?肯定不能,因为我没有把通知下发到技术部员工的手里,他们不知道这件事情,下班后他们会拍拍屁股走人,各回各家,没人会理会我的通知。我写的通知就是一张废纸,毫无用处。
想让通知起到作用,想让大家下班后留下来聚餐,我就需要给技术部全体员工下发该通知。这个地方我们可以再做个比喻,公司是整个程序,公司的运作就是程序执行的过程,公司的每个员工都是一个连接点,切点定义的规则就是“技术部全体员工”,通过切点,我就可以找到每一个技术部员工,从而把通知下发到他们的手上。之后,事情就可以顺利的执行了。
通知需要切点的匹配,才能正确的应用到连接点上,通知和切点共同定义了关于切面的全部内容——它是什么,在何时和何处完成其功能。
织入(Weaving)
简言之,就是将切面应用到连接点中。
在程序中,织入的实现,通常是利用设计模式中的代理模式,在目标对象的基础上生成新的代理对象,用代理对象去完成工作。