一、AOP的目标和原理
目标
让我们可以“专心做事”
AOP原理
-
将复杂的需求分解出不同的方面,将散步在系统中的公共功能集中解决
-
采用代理机制组装起来运行,在不改变程序的基础上对代码段进行增强处理,增加新的功能
面向切面编程,是一种通过预编译和运行期动态代理的方式实现在不修改源代码的情况下给程序动态添加功能的技术
二、AOP相关术语
增强处理(Advice)
在AOP中,增强是在特定的连接点上执行的代码,它是切面的一部分。增强定义了在何时、何地以及如何注入横切关注点的逻辑
横切关注点:
横切关注点是在软件系统中横跨多个模块的功能或关注点,它们通常不属于任何单个模块或类。横切关注点可以是诸如日志记录、性能监控、事务管理、安全性检查等与核心业务逻辑无关的功能。这些关注点会在应用程序的不同部分重复出现,而不是只存在于单个模块或类中。
在面向对象编程中,横切关注点的存在会导致代码的散乱和重复,因为相同的功能需要在多个地方进行实现。为了解决这个问题,面向切面编程(AOP)引入了横切关注点的概念。通过AOP,开发者可以将横切关注点与核心业务逻辑分离开来,将其模块化地实现,并在需要时将其应用到程序的不同部分,而无需修改核心业务逻辑的代码。
总之,横切关注点是指与核心业务逻辑无关但在整个应用程序中需要跨越多个模块或类实现的功能或关注点。通过AOP,可以更方便地管理和应用这些横切关注点,提高代码的模块化和可维护性。
- 前置增强
- 后置增强
- 环绕增强
- 异常抛出增强
- 最终增强
前置增强:前置增强是在目标方法执行前执行的增强处理
后置增强:后置增强是在目标方法执行后执行的增强处理
环绕增强:环绕增强允许开发者在目标方法执行前后都执行逻辑。它可以完全控制目标方法的执行,包括是否执行目标方法以及如何处理返回值
异常抛出增强:异常抛出增强是在目标方法抛出异常时执行的增强处理
切入点(Pointuct)
切入点是指在应用程序中定义横切关注点的位置。它是一个表达式,描述了在哪些连接点上执行特定的增强
连接点(Join Point)
连接点是在应用程序执行过程中可以应用切面的点。通常,连接点是方法的调用或异常的抛出等
切面(Aspect)
切面是横切关注点的模块化单元,它包含了切入点和增强。切面可以跨越多个类和模块,用于将横切关注点应用于多个连接点
目标对象(Target object)
目标对象是定义了切面所关注的业务逻辑的对象。切面通过将增强织入目标对象来实现横切关注点的功能
AOP代理(AOP proxy)
AOP代理是在目标对象和增强之间的中介,它拦截对目标对象的访问并应用相应的增强
织入(Weaving)
织入是将切面的增强应用到目标对象的过程。它可以在编译时、加载时或运行时完成,以确保增强逻辑与目标对象的逻辑正确地交织在一起
三、怎样使用AOP
3.1 案例:使用Spring AOP实现日志输出
实现步骤
- 在项目中添加Spring AOP的jar文件
- 编写前置增强和后置增强实现日志功能
- 编写Spring配置文件,对业务方法进行增强处理
- 编写代码获取带有增强处理的业务对象
3.2 定义切入点
切入点:简单的说,就是连接点的查询条件
<aop:config>
<aop:pointcut id="pointcut"
<!--切入点表达式,符合该表达式的方法可以被织入增强处理-->
expression="execution(public void addNewUser(entity.User))"/>
</aop:config>
表达式规则举例
<!--“*”表示匹配所有类型的返回值-->
public * addNewUser(entity.User)
<!--“*”表示匹配所有方法名-->
public void *(entity.User)
<!--“..”表示匹配所有参数个数和类型-->
public void addNewUser(..)
<!--匹配com.service包下所有类的所有方法-->
* com.service.*.*(..)
<!--匹配com.service包及其子包下所有类的所有方法-->
* com.service..*.*(..)
3.3 织入增强处理
<aop:config>
<aop:pointcut id="pointcut" expression="execution(public void addNewUser(entity.User))" />
<!--增强处理对象-->
<aop:aspect ref="userServiceLogger">
<!--前置增强处理 被织入的方法 切入点-->
<aop:before method="before" pointcut-ref="pointcut"/>
<!--前置增强处理 被织入的方法 指定需要注入返回值的属性名为result--->
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
</aop:aspect>
</aop:config>