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需要的依赖 <!--AOP相关依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> */ //把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();//获取操作方法名 com.example.tlias.conller.conllemp 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();//获取目标方法运行参数 }*/ }
springboot AOP动态代理
于 2024-01-30 17:00:58 首次发布