AOP面向切面编程

一、AOP含义

  • AOP:通过预编译方式和动态代理,可实现在不修改源代码的情况下,给程序动态同意添加的一种技术

1、模式演变

每个类每个函数都会有日志记录,产生大量重复代码;——后来形成工具类方式,每个类对象调用工具日志类,OOP:面向对象编程的方式

  • OOP的缺点
    1、形成依赖关系
    2、每个类都需要调用,如Log方法
    3、如果发生修改,每个地方都需要修改

2、AOP的应用场景

切面类一般不是核心业务逻辑

  • 日志记录
  • 权限验证:操作权限,登录,角色等
  • 事务处理
  • 效率检查:哪个方法执行效率最低(大并发情况下)
  • 异常处理:对异常统一处理,或者监控实时处理
  • 缓存处理:RedisCache
  • 数据持久化:调用方法,先存储一份
  • 内容分发:调用方法请求的时候,记录调用逻辑、方法、内容、次数等

3、AOP的主要概念

  • aspect:切面,切面由切点和通知组成,即包括横切逻辑的定义也包括链接点的定义
  • pointcut:切点,每个类拥有多个连接点,可以理解为连接点的集合
  • Joinpoint:连接点,程序执行的某个特定位置,如某个方法调用前后等(每个函数调用写日志的时候,调用方法就是连接点,多个方法的写日志,集合成为切点)
  • weaving:织入,将增强添加到目标类的具体连接点过程(过程描述)
  • advice:通知(增强),是织入到目标类的具体连接点的过程
  • target:目标对象,通知织入的目标类
  • aop Proxy:代理对象,即增强后产生的对象

4、advice的类型

  • before advice,前置通知,目标方法执行之前执行。无论是否遇到异常都会执行
  • After Returning Advice:后置通知,在方法返回后切入,抛出异常则不会切入
  • After Throwing Advice:异常通知,在方法抛出异常切入
  • After Finally Advice:最终通知,在目标方法后执行,抛出异常则不会执行
  • Around Advice:环绕通知,可以控制目标方法的执行(调用ProceedingJoinPoint.proceed()),可以在目标方法执行全过程中执行

5、@Aspect

  • 定义一个切面类Aspect
@Component
@Aspect
public class ParamLogAspect {}

  • 定义一个切点Pointcut
  /**
     * 切点名称:controller
     * 执行环境:执行过程中即:execution(表示 目标地址下所有类的所有方法,不限定参数)
     */
    @Pointcut("execution(public * com..*.controller..*.*(..))")
    public void controller() {
    }
  • 定义Advice通知
注解@Before@After@AfterReturning@AfterThrowing@Around

 @Around("@within(org.springframework.web.bind.annotation.RestController) && controller() || @within(org.springframework.stereotype.Controller) && controller()")
    public Object observer(ProceedingJoinPoint pjp) throws Throwable {}
   

ProceedingJoinPoint 只能用在Around中,其他只能用JoinPoint

  • ProceedingJoinPoint 继承了JoinPoint,在JoinPoint的基础上暴露出proceed()方法;
  • proceed是AOP代理链执行的方法
import org.aspectj.lang.reflect.SourceLocation;
public interface JoinPoint {
   String toString();         //连接点所在位置的相关信息  
   String toShortString();    //连接点所在位置的简短相关信息  
   String toLongString();     //连接点所在位置的全部相关信息  
   Object getThis();          //返回AOP代理对象,也就是com.sun.proxy.$Proxy18
   Object getTarget();        //返回目标对象,一般我们都需要它或者(也就是定义方法的接口或类,为什么会是接口呢?
                              //这主要是在目标对象本身是动态代理的情况下,例如Mapper。所以返回的是定义方法的对象如
                              //aoptest.daoimpl.GoodDaoImpl或com.b.base.BaseMapper<T, E, PK>)
   Object[] getArgs();        //返回被通知方法参数列表  
   Signature getSignature();  //返回当前连接点签名。其getName()方法返回方法的FQN,如void aoptest.dao.GoodDao.delete()
                              //或com.b.base.BaseMapper.insert(T)(需要注意的是,很多时候我们定义了子类继承父类的时候,
                              //我们希望拿到基于子类的FQN,无法直接拿到,要依赖于
                              //AopUtils.getTargetClass(point.getTarget())获取原始代理对象,下面会详细讲解)
   SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置  
   String getKind();           //连接点类型  
   StaticPart getStaticPart(); //返回连接点静态部分  
  }
 public interface ProceedingJoinPoint extends JoinPoint {
       public Object proceed() throws Throwable;
       public Object proceed(Object[] args) throws Throwable;
 }

Spring之AOP-ProceedingJoinPoint

简单的日志切面实例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值