您的位置:首页 > 编程语言 > Java开发

Spring AOP学习笔记(3):AOP返回通知&异常通知&环绕通知

2016-02-28 23:56 465 查看

一、 返回通知

返回通知,顾名思义,是在方法执行完成后,并且能够得到正常返回结果时要执行的代码,使用起来也非常简单,看下面的示例:
@AfterReturning(value="execution(* com.tools.anonymization.controller.AnonymizationController.*(..))", returning="result")
	public void loggingReturn(JoinPoint joinPoint, Object result){
		logger.info("response result:  {}", result);
	}
使用@AfterReturning注解,value字段中使用切点表达式,和之前的前置通知和后置通知一样,returning字段则是绑定到该Advice要绑定的target的返回值的参数名称,并且要在切面方法中进行声明,注意方法中的参数声明和returning字段的值一致。

二、 异常通知

异常通知是在切点表达式匹配到的方法发生异常时要运行的代码,看如下示例:
@AfterThrowing(value="execution(* com.tools.anonymization.controller.AnonymizationController.*(..))", throwing="ex")
	public void loggingThrowing(JoinPoint joinPoint, Exception ex){
		DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd EEEE HH:mm:ss");
		String time = pattern.format(LocalDateTime.now());
		File file = new File("exception.log");
		try {
			FileUtils.writeStringToFile(file, time + "\n", StandardCharsets.UTF_8, true);
			FileUtils.writeStringToFile(file, ex.getMessage() + "\n", StandardCharsets.UTF_8, true);
		} catch (FileNotFoundException e1) {
			try {
				Files.createFile(Paths.get("/"));
				FileUtils.writeStringToFile(file, time + "\n", StandardCharsets.UTF_8, true);
				FileUtils.writeStringToFile(file, ex.getMessage() + "\n", StandardCharsets.UTF_8, true);
			} catch (IOException e2) {
				e2.printStackTrace();
			}
		} catch (IOException e3) {
			e3.printStackTrace();
		}
	}
value字段含义和上述返回通知相同,throwing字段则是绑定了匹配方法发生异常时的异常类的参数名称,这也要与下面的方法中的异常类的参数名称一致。

还要注意的一点是,当参数类型是Exception时,可以在所有类型的异常发生时都会进行通知,但是如果切面方法中的参数类型与发生异常的类型不一致则不会通知,例如发生的异常是UnsupportedOperationException,但是上述方法中声明的参数类型是NullPointerException,则该方法不会进行通知。

三、 环绕通知

环绕通知,其实就是动态代理的另外一种实现,它是对匹配方法的一种包裹,可以实现前面提到的四种通知,先看如下示例:
@Around("execution(* com.tools.anonymization.controller.AnonymizationController.*(..))")
	public Object loggingAround(ProceedingJoinPoint pjp){
		Object object = null;
		
		try {
			logger.info("before logging");
			object = pjp.proceed();
			logger.info("returning logging");
		} catch (Throwable e) {
			logger.info("throwing logging");
			e.printStackTrace();
		}
		
		logger.info("after logging");
		return object;
	}
该类型的通知使用的是@Around注解,并且使用ProceedingJoinPoint代替之前的JoinPoint来获取方法的参数和签名等信息,同时通过它的实例对象来调用匹配的方法,因此这个类型的参数是必须有的。另外,该通知还必须有返回值,它的方法可以对应JDK中的动态代理中的invoke()方法,它的返回值就是Target的返回值。
在上述实例中我们也看到,之前的四种通知对应在被代理的Target的哪个位置,这样我们可以明白Advice是按照怎样的顺序执行的。但是从实践上来看,这种类型的通知并不经常用,反倒是之前的四种通知是经常被使用的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: