Spring的aop面向切面编程

横切、通知、连接点、切入点、切面???

 

横切关注点:

  • 对哪些方法进行拦截,拦截后怎么处理,这些就叫横切关注点
  • 比如 权限认证、日志、事物

通知 Advice:

所谓通知是指拦截到Joinpoint之后所要做的事情就是通知。
通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。

  • @Before前置通知

    • 在执行目标方法之前运行
  • @After后置通知

    • 在目标方法运行结束之后
  • @AfterReturning返回通知

    • 在目标方法正常返回值后运行
  • @AfterThrowing异常通知

    • 在目标方法出现异常后运行
  • @Around环绕通知

    • 在目标方法完成前、后做增强处理 ,环绕通知是最重要的通知类型 ,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint,需要手动执行 joinPoint.procced()


 

连接点 JointPoint:

所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。(通俗理解:业务层接口的所有方法都叫连接点)

切入点 Pointcut:

所谓切入点是指我们要对哪些Joinpoint进行拦截的定义。 (通俗理解:被增强的业务层接口的方法叫切入点)

(这样看来,连接点不一定是切入点,但切入点一定是连接点。)

切面 Aspect

  • 通常是一个类,里面定义 切入点+通知 , 定义在什么地方; 什么时间点、做什么事情
  • 通知 advice指明了时间和做的事情(前置、后置等)
  • 切入点 pointcut 指定在什么地方干这个事情
  • web接口设计中,web层->网关层->服务层->数据层,每一层之间也是一个切面,对象和对象,方法和方法之间都是一个个切面

目标 target

  • 目标类,真正的业务逻辑,可以在目标类不知情的条件下,增加新的功能到目标类的链路上

织入 Weaving

  • 把切面(某个类)应用到目标函数的过程称为织入

废话少说上代码

//目标类 VideoOrderService; 里面每个方法都是连接点,;切入点是CUD类型的方法,R读取的不作为切入点
//CRDU全称:增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)

public class VideoOrderService{
    //新增订单
    addOrder(){ }
    //查询订单
   findOrderById(){}
   //删除订单
   delOrder(){}
   //更新订单
   updateOrder(){}   
}


//权限切面类 = 切入点+通知 
public class PermissionAspects{
  
  //切入点  定义了什么地方
    @Pointcut("execution(public int net.xdclass.sp.service.VideoOrderService.*(..))")
  public void pointCut(){}
  
  
  //before 通知 表示在目标方法执行前切入, 并指定在哪个方法前切入
  //什么时候,做什么事情
  @Before("pointCut()")
  public void permissionCheck(){
    
    System.out.println("在 xxx 之前执行权限校验");
  }
  ....
}

//日志切面类 = 切入点+通知 
public class LogAspect{
  
  //切入点  定义了什么地方
    @Pointcut("execution(public int net.xdclass.sp.service.VideoOrderService.*(..))")
  public void pointCut(){}
  
  
  //after 通知 表示在目标方法执行后切入, 并指定在哪个方法前切入
  //什么时候,做什么事情
  @After("pointCut()")
  public void logStart(){
    
    System.out.println("在 xxx 之后记录日志");
  }
  ....
}

切入点表示式

  • 除了返回类型、方法名和参数外,其它项都是可选的 (修饰符基本都是省略不写)
        访问修饰符          返回值类型(必填)     包和类                    方法(必填)
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)  throws-pattern?) 
    • @Pointcut("execution(public int net.xdclass.sp.service.VideoOrderService.*(..))")
  • 常见匹配语法

    • *:匹配任何数量字符 单个;

    • ..:匹配任何数量字符,可以多个,在类型模式中匹配任何数量子包;在方法参数模式中匹配任何数量参数

() 匹配一个不接受任何参数的方法
(..) 匹配一个接受任意数量参数的方法
(*) 匹配了一个接受一个任何类型的参数的方法
(*,Integer) 匹配了一个接受两个参数的方法,其中第一个参数是任意类型,第二个参数必须是Integer类型

常见例子

  • 任意公共方法

    execution(public * *(..))
    
  • 任何一个名字以“save”开始的方法

    execution(* save*(..))
    
  • VideoService接口定义的任意方法(识别)

    execution(* net.xdclass.service.VideoService.*(..))
    
  • 在service包中定义的任意方法(识别)

    execution(* net.xdclass.service.*.*(..))
    
  • 匹配 service 包,子孙包下所有类的所有方法(识别)

    execution(* net.xdclass.service..*.*(..))

注解实战

@Component
//告诉spring,这个一个切面类,里面可以定义切入点和通知
@Aspect
public class LogAdvice {


    //切入点表达式
    @Pointcut("execution(* net.xdclass.sp.service.VideoServiceImpl.*(..))")
    public void aspect(){

    }

    //前置通知
    @Before("aspect()")
    public void beforeLog(JoinPoint joinPoint){
        System.out.println("LogAdvice  beforeLog");
    }


    //后置通知
    @After("aspect()")
    public void afterLog(JoinPoint joinPoint){
        System.out.println("LogAdvice  afterLog");
    }

}
@Component
//告诉spring,这个一个切面类,里面可以定义切入点和通知
@Aspect
public class LogAdvice {

    //切入点表达式,也可以直接在通知上编写切入点表达式
    @Pointcut("execution(* net.xdclass.sp.service.VideoServiceImpl.*(..))")
    public void aspect(){

    }

    //前置通知
    //@Before("aspect()")

    @Before("execution(* net.xdclass.sp.service.VideoServiceImpl.*(..))")
    public void beforeLog(JoinPoint joinPoint){
        System.out.println("LogAdvice  beforeLog");
    }


    //后置通知
    @After("aspect()")
    public void afterLog(JoinPoint joinPoint){
        System.out.println("LogAdvice  afterLog");
    }

这段代码啥意思呢?切入点定义在

@Pointcut("execution(* net.xdclass.sp.service.VideoServiceImpl.*(..))")

视频接口的实现类下的方法 在这个方法执行之前后 先执行

beforeLog()和after()这个俩方法 这个就类似登录拦截器那个一样的思想 不得不说研究出AOP的大佬是真的厉害。

方法的参数是连接点 就是每个方法都可以作为连接点 打印需要的日志。

注意 

环绕通知=前置+目标方法执行+后置通知,
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值