AOP
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP公式:
AOP(切面)=通知方法(5种)+切入点表达式(4种)
通知方法:
1.before通知 在执行目标方法之前执行
2.afterreturning 通知 在目标方法执行之后执行
3.afterthrowing 通知 在目标方法执行之后报错时执行
4.after 通知 无论什么时候程序执行完成都要执行的通知
上述的4大通知类型,不能控制目标方法是否执行.一般用来***记录程序***的执行的状态.
一般应用与监控的操作.
5.around通知(功能最为强大的) 在目标方法执行前后执行.
因为环绕通知可以控制目标方法是否执行.控制程序的执行的轨迹.
连接点问题:JoinPoint 与 ProceedingJoinPoint
JoinPoint能用在这五种通知方法中,ProceedingJoinPoint只能用在环绕通知中!
ProceedingJoinPoint中有一个核心方法proceed方法,这个方法控制目标方法执行,因为五大通知中只有around可以控制目标方法是否执行。
切入点表达式
1.bean(“bean的ID”) 粒度: 粗粒度 按bean匹配 当前bean中的方法都会执行通知.
2.within(“包名.类名”) 粒度: 粗粒度 可以匹配多个类
3.execution(“返回值类型 包名.类名.方法名(参数列表)”) 粒度: 细粒度 方法参数级别
4.@annotation(“包名.类名”) 粒度:细粒度 按照注解匹配
1.@Pointcut(“bean(itemServiceImpl)”)
2.@Pointcut(“within(com.jt.service.ItemServiceImpl)”)
3.@Pointcut(“within(com.jt.*)”) // .*一级包路径 ,..*所有子孙后代包
4.@Pointcut(“execution(* com.jt.service..*.*(..))”)
//注释: 返回值类型任意类型 在com.jt.service下的所有子孙类 以add开头的方法,任意参数类型
例:
//@Pointcut("bean(itemCatServiceImpl)")
//@Pointcut("within(com.jt.service.ItemCatServiceImpl)")
//@Pointcut("within(com.jt.service.*)") // .* 一级包路径 ..* 所有子孙后代包
//@Pointcut("execution(返回值类型 包名.类名.方法名(参数列表))")
@Pointcut("execution(* com.jt.service..*.*(..))")
//注释: 返回值类型任意类型 在com.jt.service下的所有子孙类 以add开头的方法,任意参数类型
public void pointCut(){
}
/**
* 需求:
* 1.获取目标方法的路径
* 2.获取目标方法的参数.
* 3.获取目标方法的名称
*/
@Before("pointCut()")
public void before(JoinPoint joinPoint){
String classNamePath = joinPoint.getSignature().getDeclaringTypeName();
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("方法路径:"+classNamePath);
System.out.println("方法参数:"+ Arrays.toString(args));
System.out.println("方法名称:"+methodName);
}
@Around("pointCut()")
public Object around(ProceedingJoinPoint joinPoint){
try {
System.out.println("环绕通知开始");
Object obj = joinPoint.proceed();
//如果有下一个通知,就执行下一个通知,如果没有就执行目标方法(业务方法)
System.out.println("环绕通知结束");
return null;
} catch (Throwable throwable) {
throwable.printStackTrace();
throw new RuntimeException(throwable);
}
}