AOP序言
不改你代码,就给你做增强
连接点:所有方法
1.将【共有的功能】抽取出来,放在一个通知类中
2.通知类中,定义:通知方法(里面存放:共性功能),作为通知
3.找到需要通知的方法,讲他定义为【切入点】
4.切入点与通知的关系是:切面【在哪个切入点上,执行哪些通知】
AOP入门案例
- 导入坐标
- 制作连接点方法(原始操作,Dao接口与实现类)
- 制作共性功能MyAdvice.java
- 定义切入点(需要被通知的方法)
execution()里面写:到底是什么样的方法,会被我通知
第一个参数:返回值类型
第二个参数:哪个包下、哪个类、哪个方法
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}
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(){
书写共性语句
}
}
- 配置类中,说明:我是拿注解配置的AOP
@Configuration
@ComponentScan("..")
@EnableAspectJAutoProxy//
- 查看
AOP工作流程
AOP切入点表达式
切入点:要进行增强的方法
切入点表达式:要进行增强的方法的描述方式
@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(* *..*(..)"):一切都任意,所有的都能用(很少用)
AOP通知类型
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}
@Pointcut("execution(void com.itheima.dao.BookDao.select())")
private void pt2(){}
- 前置通知
@Before("pt()")
public void before(){
在执行com.itheima.dao.BookDao.update()前做的事
}
- 后置通知
@After("pt()")
public void after(){
在执行com.itheima.dao.BookDao.update()后做的事
}
- 环绕通知【最常用】
前后都会执行
@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;
}
- 原始方法成功运行完之后
@AfterReturning("pt2()")
public void afterReturning(){
原始方法成功运行完之后,执行的动作
}
AOP通知获取数据
- 获取参数
通过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){
}
- 获取异常