(1)在方法执行之前执行的通知。前置通知使用 @Before 注解, 并将切入点表达式的值作为注解值。
/**
* 前置通知,在目标方法开始之前执行。
* 1.@Before 标记的方法的方法体.
* 2.@Before 里面的是切入点表达式
* 3.JoinPoint 类型的参数:从中可以访问到方法的签名和方法的参数.
*/
@Before("execution(public int com.shaohe.spring.aop.helloword.ArithmeticCalculator.*(int, int))")
public void beforeMethod(JoinPoint joinPoint) {
// 方法名称
String methodName = joinPoint.getSignature().getName();
// 参数数组
Object[] args = joinPoint.getArgs();
System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));
}
(2)利用方法签名编写 AspectJ 切入点表达式
(3)在 AspectJ 中, 切入点表达式可以通过操作符 &&, ||, ! 结合起来.
在目标方法执行后(无论是否发生异常),执行的通知。
后置通知是在连接点完成之后执行的, 即连接点返回结果或者抛出异常的时候
/**
* 后置通知:@After,在方法执行之后执行的代码.
*/
@After("execution(* com.shaohe.spring.aop.helloword.*.*(..))")
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("The method " + methodName + " ends");
}
在方法正常结束后执行
/**
* 返回通知:在方法正常结束后执行的代码
* 返回通知是可以访问到方法的返回值的!
* value属性或者pointcut属性中填写切点表达式
* returning:和通知的参数名相同,都是result
*/
@AfterReturning(value = "execution(* com.shaohe.spring.aop.helloword.*.*(..))", returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("返回通知:The method " + methodName + " ends with " + result);
}
只在连接点抛出异常时才执行
/**
* 异常通知:只在连接点抛出异常时才执行
*/
@AfterThrowing(value = "execution(* com.shaohe.spring.aop.helloword.*.*(..))", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, Exception e) {
String methodName = joinPoint.getSignature().getName();
System.out.println("异常通知:The method " + methodName + " occurs excetion:" + e);
}
/**
* 环绕通知:相当于动态代理的全过程
* ProceedingJoinPoint类型的参数可以决定是否执行目标方法
* 必须有返回值,即目标方法的返回值。
*/
@Around("execution(* com.shaohe.spring.aop.helloword.*.*(..))")
public Object aroundMethod(ProceedingJoinPoint pjd) {
Object result = null;
String methodName = pjd.getSignature().getName();
try {
// 前置通知
System.out.println("环绕通知-前置通知:The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));
// 执行目标方法
result = pjd.proceed();
// 返回通知
System.out.println("环绕通知-返回通知:The method " + methodName + " ends with " + result);
} catch (Throwable e) {
// 异常通知
System.out.println("环绕通知-异常通知:The method " + methodName + " occurs exception:" + e);
throw new RuntimeException(e);
}
// 后置通知
System.out.println("环绕通知-后置通知:The method " + methodName + " ends");
// 返回值,即目标方法的返回值。
return result;
}
声明切面:
public class LoggingAspectXML {
/**
* 前置通知,在目标方法开始之前执行
*/
public void beforeMethod(JoinPoint joinPoint) {
// 方法名称
String methodName = joinPoint.getSignature().getName();
// 参数数组
Object[] args = joinPoint.getArgs();
System.out.println("前置通知:The method " + methodName + " begins with " + Arrays.asList(args));
}
/**
* 后置通知:,在方法执行之后执行的代码.
*/
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("后置通知:The method " + methodName + " ends");
}
/**
* 返回通知:在方法正常结束后执行的代码
* 返回通知是可以访问到方法的返回值的!
*/
public void afterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("返回通知:The method " + methodName + " ends with " + result);
}
/**
* 异常通知:只在连接点抛出异常时才执行
*/
public void afterThrowing(JoinPoint joinPoint, Exception e) {
String methodName = joinPoint.getSignature().getName();
System.out.println("异常通知:The method " + methodName + " occurs excetion:" + e);
}
}
xml配置:
启动测试:
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-aop-xml.xml");
// 从IOC容器中获取Bean的实例
ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) ctx.getBean("arithmeticCalculator");
// bean的类型名称
System.out.println(arithmeticCalculator.getClass().getName());
// 调用bean的方法。
int result = arithmeticCalculator.add(11, 12);
System.out.println("result:" + result);
}
引入通知是一种特殊的通知类型. 它通过为接口提供实现类, 允许对象动态地实现接口, 就像对象已经在运行时扩展了实现类一样.