术语说明
- 目标target,被增强的对象
- 连接点Joinpoint,指的是可以被拦截到的方法
- 切入点Pointcut,指的是真正被拦截到的方法
- 通知Advice,指的是拦截到切入点后要做的事情
- 织入Weaving,指的是将通知Advice应用到目标target的这个过程
- 代理Proxy,目标Target被增强后,产生了一个代理对象
- 切面Aspect,切入点Pointcut和通知Advice的组合
实现原理
- JDK动态代理(目标类实现了接口)
- Cglib动态代理(目标类无接口实现)
切入点表达式
参数包括:execution("修饰符 返回值类型 包.类.方法名(参数..) throws异常")
- 修饰符(举例):一般省略
* 任意
public 公共访问
- 返回值(举例):
void 无返回值
String 返回值是字符串类型
* 返回值任意
- 包(举例):
com.xx.user.dao 固定包
com.xx.*.dao com.xx下的任意包中的dao包
com.xx.user.dao.. 包括dao下所有子包中
- 类(举例):
UserDaoImpl 具体类
User* 以User开头类
*User 以User结尾类
* 任意类
- 方法(举例):
addUser 具体方法
* 任意方法
*User 以add结尾方法
add* 以add开头方法
- 参数(无参):
() 无参
(..) 任意参数
(String, int) 1个String和1个int类型的参数
(int) 1个int类型参数
- throws,可省略一般不写
通知类型
@Aspect
@Component
public class MyAspect {
/**
* 定义一个切入点表达式,表示需要应用的切入点
*/
@Pointcut("execution(* org.example.aop.AopTarget.*(..))")
public void firstJoinPoint() {
}
/**
* 前置通知
* @param joinPoint
*/
@Before("firstJoinPoint()")
public void before(JoinPoint joinPoint) {
System.out.println("@Before前置通知");
}
/**
* 后置通知
* @param joinPoint
* @param result
*/
@AfterReturning(value = "firstJoinPoint()", returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result) {
System.out.println("@AfterReturning后置通知结果为:" + result);
}
/**
* 环绕通知
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("firstJoinPoint()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("@Around环绕通知=前");
Object obj = joinPoint.proceed();
System.out.println("@Around环绕通知=后");
return obj;
}
/**
* 异常抛出通知
* @param e
*/
@AfterThrowing(value = "firstJoinPoint()", throwing = "e")
public void afterThrowing(Throwable e) {
System.out.println("@AfterThrowing异常抛出通知" + e.getMessage());
}
/**
* 最终通知
*/
@After("firstJoinPoint()")
public void after() {
System.out.println("@After最终通知");
}
/**
* 打印切点属性
* @param joinPoint
*/
private void printJoinPoint(JoinPoint joinPoint) {
System.out.println("目标方法名为:" + joinPoint.getSignature().getName());
System.out.println("目标方法所属类的简单类名:" + joinPoint.getSignature().getDeclaringType().getSimpleName());
System.out.println("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());
System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));
// 获取传入目标方法的参数
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
System.out.println("第" + (i + 1) + "个参数为:" + args[i]);
}
System.out.println("被代理的对象:" + joinPoint.getTarget());
System.out.println("代理对象自己:" + joinPoint.getThis());
}
}