面向对象编程(OOP)和面向切面编程(AOP)都是一种编程方式,AOP 可以作为 OOP 的补充。为什么说是补充了,其实就是 OOP 在某些场景不好处理,而 AOP 却能很好处理。
无论是 AOP,还是 OOP,它们的目标是一致的:让代码变得易扩展和可读性强。
OOP 里面,我们主要通过继承和组合等方式提供扩展能力。当然,OOP 原则是让我们少用继承,多用组合。后面我会结合一个例子来说明原因。
AOP 也不例外,提供了一种新的扩展能力。继承的扩展对象是一个或多个类,Java 是单继承机制,只能对一个类进行扩展;而 AOP 扩展对象是切面,由不同类里面的一个或者多个方法组成。如果把类的继承看做纵向扩展,那么 AOP 就是一个横向扩展。到底是由哪些类的哪些方法来组成切面呢?这个就是由切点来描述。通过 AOP 实现的扩展代码,我们就叫它切面代码。
那么 AOP 可以理解为这样的一个过程:切点定位类中的一系列方法,多个切点组合成一个切面,切面代码实现了扩展的能力,最后将切面代码编织到切面中的所有切点里面去。(编织的时候,还有一个通知的概念被省略了,通知其实是用来描述切面代码编织到切点的时机)
举例说明:一个非常经典的例子:事务的管理。
**
很多服务类都需要编写事务管理相关的代码。怎么把这些重复的代码抽象出来呢?一种比较容易想到的方式是抽象一个父类,把这些相同的代码放到父类中,子类继承该父类,则自然拥有了父类的事务管理能力。
但是通过继承做抽象不是很优雅,因为继承对业务代码侵入性太强,业务代码不得不继承一个父类。像 Java 本身即是单继承机制,业务子类如果还相继其他的父类就会很麻烦了。这也是为什么 OOP 原则中有一条少用继承,多用组合的原因。
目前最好的方式是通过 AOP 抽象事务管理相关的代码。该方式对业务代码侵入性最小,只需要在类或者方法上加相关的注解,框架则自动将事务管理相关的代码编织到目标类的方法里面去。