1. AOP的核心理念
封装:冗余且不得不执行的代码放到AOP中执行
公式: AOP = 切入点表达式 + 通知方法
2. 切入点表达式
- bean(bean的ID) 按照指定的bean名称拦截用户的请求,之后执行通知方法. 只能匹配单个bean对象
- within(包名.类名) 可以按照类通配的方式去拦截用户的请求. 控制粒度较粗.
- execution(返回值类型 包名.类名.方法名(参数列表)) 方法参数级别 控制粒度较细
- @annotation(包名.注解名称) 按照注解的方式去拦截用户请求.
3. 通知方法
-
前置通知: 主要在 目标方法执行之前执行
-
后置通知: 在目标方法执行之后执行
-
异常通知: 在目标方法执行的过程中报了异常之后执行.
-
最终通知: 无论什么时候都要执行的通知方法.
上述的通知方法,无法控制目标方法是否执行.所以一般"只做记录不做改变" -
环绕通知: 一般采用环绕通知 实现对业务的控制.
4. AOP入门案例
//1.将对象交给容器管理
@Component
//2.定义aop切面
@Aspect
public class CacheAOP {
//公式: 切面 = 切入点表达式 + 通知方法.
/**
* @Pointcut 切入点表达式 可以理解为就是一个if判断,只有满足条件,才能执行通知方法.
*/
//@Pointcut("bean(beanid)") //按类匹配,控制的粒度较粗 单个bean
//@Pointcut("within(com.jt.service..*)") //按类匹配,控制的粒度较粗 多个bean
@Pointcut("execution(* com.jt.service..*.*(..))") //细粒度的匹配方式
public void pointCut() {
}
//joinPoint 方法执行切恰好被切入点表达式匹配,该方法的执行就称之为连接点.
@Before("pointCut()")
public void before(JoinPoint joinPoint) {
System.out.println("我是前置通知!!!!");
String typeName =
joinPoint.getSignature().getDeclaringTypeName();
String methodName = joinPoint.getSignature().getName();
Object[] objs = joinPoint.getArgs();
Object target = joinPoint.getTarget();
System.out.println("方法执行的全路径为:"+typeName+"."+methodName);
System.out.println("获取方法参数:"+objs);
System.out.println("获取目标对象:"+target);
}
//添加环绕通知 可以控制目标方法执行 要求添加参数
@Around("pointCut()")
public Object around(ProceedingJoinPoint joinPoint) {
System.out.println("我是环绕通知开始");
try {
//Object result = joinPoint.proceed();
System.out.println("我是环绕通知结束");
return null;
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
} //指定目标方法
}
}