4.Spring-AOP

88 阅读2分钟

AOP序言

不改你代码,就给你做增强

图片.png

连接点:所有方法
1.将【共有的功能】抽取出来,放在一个通知类中
2.通知类中,定义:通知方法(里面存放:共性功能),作为通知
3.找到需要通知的方法,讲他定义为【切入点】
4.切入点与通知的关系是:切面【在哪个切入点上,执行哪些通知】

图片.png

图片.png

AOP入门案例

图片.png

  1. 导入坐标

图片.png

  1. 制作连接点方法(原始操作,Dao接口与实现类)

图片.png

  1. 制作共性功能MyAdvice.java

图片.png

  1. 定义切入点(需要被通知的方法)
execution()里面写:到底是什么样的方法,会被我通知
第一个参数:返回值类型
第二个参数:哪个包下、哪个类、哪个方法
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}

图片.png 5. 绑定共性功能和切入点的关系(切面)

@Component //受Spring管理
@Aspect //并且告诉Spring,我是AOP
public class MyAdvice{
    @Pointcut("execution(void.com.itheima.dao.BookDao.update())")
    private void pt(){}
    
    @Before("pt()")//我准备让下面这个方法,在我Pointcut切入点指定的方法之前执行
    public void method(){
        书写共性语句
    }
}
  1. 配置类中,说明:我是拿注解配置的AOP
@Configuration
@ComponentScan("..")
@EnableAspectJAutoProxy//
  1. 查看

图片.png

AOP工作流程

图片.png

图片.png

AOP切入点表达式

切入点:要进行增强的方法
切入点表达式:要进行增强的方法的描述方式

图片.png

图片.png

图片.png

@Pointcut("execution(* com.itheima.dao.impl.BookDaoImpl.update())"):返回值不限定

@Pointcut("execution(* com.itheima.dao.impl.BookDaoImpl.update(*))"):update中有数量>0的参数

@Pointcut("execution(void *..update())"):不管你有多少层包,只要有update都可以

@Pointcut("execution(* *..*(..)"):一切都任意,所有的都能用(很少用)

图片.png

AOP通知类型

图片.png

@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}

@Pointcut("execution(void com.itheima.dao.BookDao.select())")
private void pt2(){}
  1. 前置通知
@Before("pt()")
public void before(){
    在执行com.itheima.dao.BookDao.update()前做的事
}
  1. 后置通知
@After("pt()")
public void after(){
    在执行com.itheima.dao.BookDao.update()后做的事
}
  1. 环绕通知【最常用】
前后都会执行
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) thorws Throwable{
    System.out.println("执行前的操作")
    
    //表示对原始操作的调用,执行com.itheima.dao.BookDao.update()方法
    //pjp.proceed();
    
    //原始方法可能会有返回值,我们在这里也要接收一下
    Object ret = pjp.proceed();
    
    System.out.println("执行后的操作")
    
    return ret;
}
  1. 原始方法成功运行完之后
@AfterReturning("pt2()")
public void afterReturning(){
    原始方法成功运行完之后,执行的动作
}

AOP通知获取数据

图片.png

  1. 获取参数

通过JointPoint获取参数

@Pointcut("execution(* com.itheima.dao.BookDao.findName(..))")
private void pt(){}

@Before("pt()")
public void before(JoinPoint jp){
    获取到com.itheima.dao.BookDao.findName(..)参数
    Object[] args = jp.getArgs();
    Arrays.toString(args)
}

通过Around中的ProceedingJoinPoint

@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable{
    Object[] args = pjp.getArgs()
    
    Object ret = pjp.proceed();
    return ret
}

通过AfterReturning【只有成功返回值,我才执行】 returning = "XX" XX和参数名一样

@AfterReturning(value = "pt()",returning = "ret")
public void afterReturning(Object ret){
    ...
}

如果AfterReturning中含有JoinPoint,这个参数需要在ret前面

@AfterReturning(value = "pt()",returing = "ret")
public void afterReturning(JoinPoint jp,Object jet){
    
}
  1. 获取异常

图片.png

图片.png

图片.png