springboot AOP动态代理

package com.example.tlias.AOPbao;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/*AOP是什么:
动态代理是面向切面编程最主流的实现。
而SpringAOP是Spring框架的高级技术,
旨在管理bean对象的过程中,
主要通过底层的动态代理机制,对特定的方法进行编程
其他就是一个动态代理可以增强或者增加一个或者多个方法功能

AOP需要的依赖


org.springframework.boot
spring-boot-starter-aop
    */

//把AOP类加入IOC  ben里
@Component

//@Aspect  表示这是一个AOP类
@Aspect

//日志注解
@Slf4j
public class AOPdongtaidaili {
   /*@Pointcut该注解的作用是将公共的切点表达式抽取出来,
       需要用到时引用该切点表达式即可。 抽取共性内容
      比如@Around("pt()")这样调用
   */

    @Pointcut("execution(* com.example.tlias.sevicechuli.*.*(..))")
    public void pt() {
    }

       /*
      AOP常用注解:
     1. @Around:  环绕通知,此注解标注的通知方法在目标方法前、后都被执行 只这个方法需要添加形参
      ProceedingJoinPoint   joinPoint   调用   joinPoint.proceed(); 来让原始方法执行,
      其他通知不需要考虑目标方法执行
      @Around环绕通知方法的返回值,必须指定为0bject,来接收原始方法的返回值。

     2. @Before:   前置通知,此注解标注的通知方法在目标方法前被执行
     3. @After :   后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行
     4. @AfterReturning :  返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
     5. @AfterThrowing:   异常后通知,此注解标注的通知方法发生异常后执行
      */

      /*
   AOP切入点解析
  @Around表示切这是一个AOP类

   1.execution切入点表达式写法
   注意空格 ?号表示可以省略
   切入点表达式格式   execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数)throws 异常?)
   切入点表达式: @Around("execution(* com.example.tlias.sevicechuli.*.*(..))")
   这里的*表示可以任意返回值

    1.com.example.tlias.sevicechuli需要代理的类或接口所存放的位置
    2.  *  :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,
    也可以通配包、类、方法名的一部分比如delete*表示delete开头的任意方法都可以
    可以写成@Around("execution(* com.itheima.*.impl.DeptServiceImpl.*())")

   @Around("execution(* com.itheima.*.impl.DeptServiceImpl.*(..))")
    3.   ..  : 多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数
    注意他只能替换包和形参和*不同的是他表示可以是任意数量  *表示一个*表示一个
    比如@Around("execution(* com.itheima.*.impl.DeptServiceImpl.*(*))")只能表示一个哦

    4.如果是@Around("execution(* com.itheima.service.impl.DeptServiceImpl.list ())")
    表示只list ()方法被代理

    5.也可以加上 &&  || !  符号比如
    @Around("execution(* com.itheima.service.impl.DeptServiceImpl.list ()) ||  execution(* com.itheima.service.impl.DeptServiceImpl.list ()) ")
   */

      /*  1.不同切面类中,默认按照切面类的类名字母排序:
       ◆目标方法前的通知方法:字母排名靠前的先执行.
       比如方法名字 ABC1和BAC1  则ABC1先执行 比完第一个字母一样接着比第二个以此类推

       ◆目标方法后的通知方法:字母排名靠前的后执行
       比如方法名字 ABC1和BAC1  则BAC1先执行 比完第一个字母一样接着比第二个以此类推

     2.用 @Order(数字) 加在切面类上来控制顺序
              目标方法前的通知方法:数字小的先执行
              比如:
              @Order(1)
              @Around("pt()")
              public Object aopp(ProceedingJoinPoint joinPoint){}

              目标方法后的通知方法:数字小的后执行
               比如:
              @Order(1)
              @Around("pt()")
              public Object aopp(ProceedingJoinPoint joinPoint){}
            */

       /*
      2.@annotation()切入点表达式写法是基于自定义注解的只要加上注解就会执行
       1.自定义注解实例:
       @Retention(RetentionPolicy.RUNTIME)//这个注解表示这是一个运行时期注解
      @Target(ElementType.METHOD)//这个注解表示可以加在方法上
       public @interface mylog { }

          2.具体演示代码:
         1.需要被执行方法:
          @mylog  //加上就会执行
          public void add(dept poST) {}

        2.抽出共同的切入点表达式写法:
       @Pointcut("@annotation(* com.example.tlias.sevicechuli.mylog")
       public void pt(){}
      */

     /*
     连接点:
     在Spring中用joinPoint抽象了连接点,用它可以获得方法执行时的相关信息,
     如目标类名、方法名、方法参数等,
     连接点就是AOP目前方法执行前后需要执行的方法
      这里主要介绍joinPoint里面形参的 如何获取类名、方法名、方法参数
      joinPoint是ProceedingJoinPoint的父类他们的方法是共用的可以用在除@Around
      环绕通知以外的注解上

        1.实例代码:
         @Order(1)
        @Around("pt()")//切入点表达式
        //加入ProceedingJoinPoint joinPoint  表示那个类需要被AOP动态代理
        public void aopp(JoinPoint zhixing) throws Throwable {

        String name = zhixing.getTarget().getClass().getName();  //获取目标类名
        Signature signature = zhixing.getSignature();  //获取目标方法签名
        String name1 = zhixing.getSignature().getName();//获取目标方法名
        Object[] args = zhixing.getArgs();//获取目标方法运行参数
    }
     */


    @Order(1)
    @Around("pt()")//切入点表达式
    //加入ProceedingJoinPoint joinPoint  表示那个类需要被AOP动态代理
    public Object aopp(ProceedingJoinPoint joinPoint) throws Throwable {
        long l = System.currentTimeMillis();

        //调用被代理的原方法
        Object proceed = joinPoint.proceed();//环绕通知专属

        long l2 = System.currentTimeMillis();

        long shu = l - l2;

        //记录时间日记输出用时
        log.info("当前方法所需用时" + shu + "毫秒");

        return proceed;

    }

    /*@Order(1)
    @Around("pt()")//切入点表达式
    //加入ProceedingJoinPoint joinPoint  表示那个类需要被AOP动态代理
    public void aopp(JoinPoint zhixing) throws Throwable {

        String name = zhixing.getTarget().getClass().getName();  //获取目标类名
        Signature signature = zhixing.getSignature();  //获取目标方法签名
        String name1 = zhixing.getSignature().getName();//获取目标方法名
        Object[] args = zhixing.getArgs();//获取目标方法运行参数

    }*/

}

你可能感兴趣的:(spring,boot,java,后端)