AOP(1)

本文深入探讨了面向方面编程(AOP)的概念及其在Spring框架中的应用,包括连接点、切入点、通知、切面等核心概念。详细解释了如何通过代理模式和拦截器模式在程序中织入横切关注点,以及不同类型的AOP通知(如前置、后置、环绕等)如何影响程序执行流程。

概述

面向方面编程(AOP)也可叫做面向切面编程,是一种编程范式,用于完善面向对象编程(OOP),是Spring两大特征之一(IoC和AOP)
OOP基于组件(类)进行开发,然后对组件进行组合,无法解耦组件进行开发

基本概念

  • 连接点(Joinpoint):表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或者异常处理等等,Spring只支持方法执行的连接点

  • 切入点(Pointcut):选择一组相关连接点的模式,即可以认为连接点的集合,Spring支持perl5正则表达式和AspectJ切入点模式,Spring默认使用AspectJ语法

  • 通知(Advice):在连接点上执行的行为,通知提供了在AOP需要在切入点所选择的连接点处进行扩展现有行为的手段,包括前置通知(before advice)、后置通知(after advice)、环绕通知(around advice)、在Spring中通过代理模式实现AOP、并通过拦截器模式以环绕连接点的拦截器链织入通知

  • 切面(Aspect):横切关注点的模块化。可以认为是通知、引入和切入点的组合;在Spring中可以使用Schema和@AspectJ方式进行组织实现

  • 引入(inter-type declaration):也成为内部类型声明。为已有的类添加额外新的字段或者方法,Spring允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象)

  • 目标对象(Target Object):需要被织入横切关注点的对象,即对象是切入点选择的对象,需要被通知的对象,从而也可以成为“被通知对象”;由于Spring AOP通过代理模式实现,从而这个对象永远是被代理对象

  • AOP代理(AOP proxy):AOP框架使用代理模式创建对象,从而实现在连接点处插入通知(应用切面),就是通过代理来对目标对象应用切面。Spring中,AOP代理可以用JDK动态代理或者CGLIB代理实现,而通过拦截器模型应用切面

  • 织入(Weaving):织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期,类装载期,运行期进行

通知类型

  • 前置通知
    在切入点选择的连接点处的方法之前执行的通知,该通知不影响程序正常执行流程(除非该通知抛出异常,该异常将中断当前方法链的执行而返回)
  • 后置通知
    在切入点选择的连接点处的方法之后执行的通知,包括以下
    • 后置返回通知
      在切入点选择的连接点处的方法正常执行完毕时执行的通知,必须是连接点处的方法没有抛出任何异常,正常返回时才调用后置通知
    • 后置异常通知
      在切入点选择的连接点处的方法抛出异常返回时执行的通知,必须是连接点处的方法抛出任何异常,返回时才调用后置通知
    • 后置最终通知
      在切入点选择的连接点处的方法返回时执行的通知,不管有没有抛出异常都执行
  • 环绕通知
    环绕着在切入点选择连接点处的方法所执行的通知,环绕通知可以在方法调用之前和之后定义任何行为,并且可以决定时候执行连接点处的方法,替换返回值,抛出异常等等

AOP代理

AOP代理就是AOP框架通过代理模式创建的对象,Spring使用JDK动态代理或者CGLIB代理来实现,Spring缺省(默认)使用JDK动态代理来实现,从而任何接口都可被代理,如果被代理的对象实现不是接口将默认使用CGLIB代理(CGLIB动态代理),不过CGLIB代理当然也可应用到接口。

Java AOP,一般称为面向切面,作为面向对象OOP的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块之间的耦合度,提高了系统的可维护性,可用于权限认证,日志和事务处理[^4]。 使用Java AOP的方法步骤如下: 1. **依赖引入**:在项目中添加AOP相关依赖,确保项目能够使用AOP的功能。 2. **标注为切面**:使用特定注解将标注为切面,表明该是一个AOP切面。 3. **定义切入点函数列表**:确定哪些方法会被AOP拦截和增强,通过特定的表达式来定义。 4. **定义签名函数**:定义在切入点函数执行前后等不同时机要执行的具体方法。 5. **增强方法**:实现具体的增强逻辑,如前置通知、环绕通知、后置通知、返回通知、报错通知等。 6. **aop全局注解**:可以使用全局注解来简化配置和使用。 以下是一些Java AOP的案例: ### 案例一:基于Spring Boot的简单实践 1. **依赖引入**:添加相关依赖。 2. **项目包结构**:搭建好项目的包结构。 3. **项目启动**:启动项目的主。 4. **切面**: - **创建**:创建切面。 - **切点实现**:定义切入点。 - **前置通知**:在目标方法执行前执行的通知。 - **环绕通知**:可以在目标方法执行前后进行操作。 - **后置通知**:在目标方法执行后执行的通知。 - **返回通知**:在目标方法正常返回后执行的通知。 - **报错通知**:在目标方法抛出异常时执行的通知。 - **完整切面代码**:整合上述各种通知的完整代码。 5. **请求接口的实现**:创建多个请求接口,如AopTestController.java、AopTest2Controller.java、AopTest3Controller.java。 6. **测试接口**:对不同请求接口的方法进行测试。 7. **输出打印**:查看不同测试方法的输出结果。 ### 案例二:简单实例演示 1. **包结构**:搭建项目的包结构。 2. **依赖**:添加AOP相关依赖。 3. **项目启动**:启动项目的主。 4. **请求**:创建请求。 5. **切面**:实现切面逻辑。 6. **执行AOP**: - **启动程序**:启动项目。 - **postman访问**:使用postman工具访问接口。 - **控制台输出**:查看控制台的输出结果。 ### 案例三:入门案例 ```java public class AspectAop1 { @Pointcut("execution(* com.********.************Impl.*(..))") public void pt(){ } @Before("pt()") public void before(){ System.out.println("之前aop1"); } @AfterReturning("pt()") public void afterReturing(){ System.out.println("执行之后,抛出异常不会执行aop1"); } @After("pt()") public void after(){ System.out.println("最后执行aop1"); } @AfterThrowing(value = "pt()",throwing = "e") public void afterTh(Throwable e){ e.printStackTrace(); System.out.println("异常通知增强aop1"); } } ``` ### 案例四:Spring Aop案例 ```java package org.example.aop; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component @Aspect//当作Aop处理 public class MyAdvice { @Pointcut("execution(void org.example.dao.BookDao.update())") private void pt(){} @Before("pt()") public void method(){ System.out.println(System.currentTimeMillis()); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值