探秘SpringAop_介绍以及使用详解

Posted 养码青年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了探秘SpringAop_介绍以及使用详解相关的知识,希望对你有一定的参考价值。

常用的编程范式

AOP 是什么

  • 是一种编程方式,不是编程语言

  • 解决特定问题,不能解决所有的问题

  • OOP的补充,不是代替

AOP 初衷

  • DRY: Don't repeat yourself(代码重复)

  • SoC:Separation of Concerns(关注点分离)

    • 水平分离:展示层-> 服务层 -> 持久层

    • 垂直分离:模块划分(订单、库存等)

    • 切面分离:分离功能性需求与非功能性需求

AOP的优点

  • 集中处理某一关注点/横切逻辑

  • 可以很方便地添加/删除关注点

  • 侵入性少,增强代码可读性及可维护性

AOP的应用场景

  • 权限控制

  • 缓存控制

  • 性能监控

  • ...

支持AOP的语言

  • Java、Python、php...


SpringAOP使用详解

首先,我整理了一张图,让大家更好的梳理SpringAOP的使用

@Poincut 详解

匹配包/类型_ within()
  • 匹配ProductService类里头的所有方法


  • @Pointcut("within(com.zhb.service.ProductService)")


  • 匹配com.zhb包及子包下所有类的方法


  • @Pointcut("within(com.zhb..*)")


匹配对象
  • 匹配AOP对象的目标对象为指定类型的方法,即LogService的aop代理对象的方法


  • @Pointcut("this(com.zhb.log.Loggable)")


  • 匹配实现Loggable接口的目标对象(而不是aop代理后的对象)的方法


  • @Pointcut("target(com.zhb.log.Loggable)")


  • this 可以拦截 DeclareParents(Introduction)


  • target 不拦截 DeclareParents(Introduction)


  • 匹配所有以Service结尾的bean里头的方法


  • @Pointcut("bean(*Service)")


匹配参数 args()
  • 匹配任何以find开头而且只有一个Long参数的方法


  • @Pointcut("execution(* ..find(Long))")


  • 匹配任何以find开头的而且第一个参数为Long型的方法


  • @Pointcut("execution(* ..find(Long,..))")


  • 匹配任何只有一个Long参数的方法


  • @Pointcut("within(com.zhb..*) && args(Long)")


  • 匹配第一个参数为Long型的方法


  • @Pointcut("within(com.zhb..*) && args(Long,..)")


匹配注解
  • 匹配方法标注有AdminOnly的注解的方法

  • @Pointcut("@annotation(com.zhb.anno.AdminOnly) && within(com.zhb..*)")

  • 匹配标注有NeedSecured的类底下的方法 //class级别

  • @Pointcut("@within(com.zhb.anno.NeedSecured) && within(com.zhb..*)")

  • 匹配标注有NeedSecured的类及其子类的方法 //runtime级别

  • 在spring context的环境下,二者没有区别

  • @Pointcut("@target(com.zhb.anno.NeedSecured) && within(com.zhb..*)")

  • 匹配传入的参数类标注有Repository注解的方法

  • @Pointcut("@args(com.zhb.anno.NeedSecured) && within(com.zhb..*)")

匹配方法
  • 匹配任何公共方法


  • @Pointcut("execution(public * com.zhb.service..(..))")


  • 匹配com.zhb包及子包下Service类中无参方法


  • @Pointcut("execution(* com.zhb..Service.())")


  • 匹配com.zhb包及子包下Service类中的任何只有一个参数的方法


  • @Pointcut("execution(* com.zhb..Service.(*))")


  • 匹配com.zhb包及子包下任何类的任何方法


  • @Pointcut("execution(* com.zhb...(..))")


  • 匹配com.zhb包及子包下返回值为String的任何方法


  • @Pointcut("execution(String com.zhb...(..))")


  • 匹配异常


  • execution(public * com.zhb.service..(..) throws java.lang.IllegalAccessException)


其实,这么多实际工作中用到的比较少,我平时就用过execution 这一个。

Advice 详解

  • @Before(value = "matchLongArg() && args(productId)")

  • public void beforeWithArgs(Long productId)

  • @AfterReturning(value = "matchReturn()",returning = "returnValue")

  • public void getReulst(Object returnValue)

给出一段常用代码

 
   
   
 
  1.    @Pointcut("within(com.zhb.controller.GirlController)")

  2.    public void mathType(){}

  3.    @Before(value = "mathType() && args(obj)")

  4.    public void before(Object obj){

  5.        System.out.println("这里是目标方法执行前先执行");

  6.        //获取参数

  7.        System.out.println("这里是目标方法的参数"+obj.toString());

  8.    }

  9.    @AfterReturning(returning = "entity",value = "mathType()")

  10.    public void after(JoinPoint joinPoint,Object entity){

  11.        System.out.println("这里是目标方法执行完并成功返回结果 正常结束后才执行");

  12.        System.out.println("方法的返回结果为"+entity);

  13.        System.out.println("目标方法内的参数为"+ Arrays.asList(joinPoint.getArgs()));

  14.    }

  15.    @AfterThrowing(throwing = "e",value = "mathType()")

  16.    public void mathThrow(Throwable  e){

  17.        System.out.println("这里是目标方法抛出异常后才执行");

  18.        System.out.println("异常信息为"+e);

  19.    }

大家再用到的时候可以自行搜索


以上是关于探秘SpringAop_介绍以及使用详解的主要内容,如果未能解决你的问题,请参考以下文章

Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现

探秘手淘高可用平台——热修复和开发流程

Python中verbaim标签使用详解

探秘蚂蚁金服分布式事务 Seata 的ATSaga和TCC模式

Spring框架学习05——AOP相关术语详解

JVM系列 - JVM对象探秘