Spring-AOP的五种通知和切面的优先级、通知变量声明

SpringAOP的通知分为以下五种:

1前置通知(@before)
在连接点执行之前执行的代码

2后置通知(@after)
在连接点执行之后执行的代码,不管连接点执行后是否出现异常,后置通知都会执行,但是不能访问连接点返回值

3返回通知
返回通知:就是可以获取连接点的返回值,
      当连接点执行之后,若没有异常,则执行返回通知,返回通知在后置通知执行后才会执行

4异常通知
在连接点执行的时候,若出现异常,则会执行异常通知,可以根据异常类型来定义执行对应的异常通知

5环绕通知
相当于一个动态代理,也就是说其动能包括了前面四个通知的功能,

示例代码:

package com.jeremy.aop.example;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/*
 * 使用AOP的步骤
 * 1声明一个切面,切面必须是在IOC容器中,所以必须添加@component注解,而且还说明是一个切面,所以还要添加@Aspect注解
 * 2定义通知:通知有五种,分别是前置通知、后置通知、返回通知、异常通知、环绕通知,根据业务需求定义所需的通知
 * 3在通知里说明通知时由那个类的那个方法执行
 * 4在Spring的配置文件自动扫描<context:component-scan>和配置AspectJ
 * 配置AspectJ是当我们调用一个目标方法时,而这个目标方法跟我注解声明的方法相匹配的时候,那么AOP框架应该自动的为那个方法所在的那个类生成一个代理对象,
 * 在我目标方法执行之前先来执行切面的对应的方法
 */

@Aspect
@Component
public class LoggingAspect {
	@Before("execution(* com.jeremy.aop.example.ArithmeticCalculator.*(..))")
	private void beforeMethod() {
		System.out.println("the Method begins........");

	}
	
	
	@After("execution(* com.jeremy.aop.example.ArithmeticCalculator.*(..))")
	private void afterMethod() {
		// TODO Auto-generated method stub
		System.out.println("The Method after ................");
	}
	
	@AfterReturning(value="execution(* com.jeremy.aop.example.ArithmeticCalculator.*(..))",returning="result")
	
	public void AfterReturning(JoinPoint joinPoint,Object result){
	
		System.out.println("The Method after ................"+result);
	}
	
	@AfterThrowing(value="execution(* com.jeremy.aop.example.ArithmeticCalculator.*(..))",throwing="e")
	public void AfterThrowing(JoinPoint joinPoint,Exception e){
		System.out.println("The Method afterThrowing  ................"+e.getMessage().toString());
	}
	
	@Around(value="execution(* com.jeremy.aop.example.ArithmeticCalculator.*(..))")
	public Object aroundTest(ProceedingJoinPoint pjp){
		
		String methodName=pjp.getSignature().getName();
		Object object=null;
		try {
			
			// 前置通知
			 
			System.out.println("The Method "+methodName+"before  ................");
			object=pjp.proceed();
			//返回通知
			System.out.println(object);
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			//异常通知
			System.out.println(e.getMessage().toString());
		}
		System.out.println("The Method "+methodName+"    after  ................");
		return object;
	}
}

  

切面优先级:也就是切面运行的先后

      比如当我们一个系统涉及权限,日志,验证。。等等各种功能我们一般是需要先验证有没有这个权限,然后再打印日志,但是系统并不知道怎么去识别使用哪个切面

      所以我们就要硬性的规定一下优先使用哪个切面(使用@order注解既可以了)
示例:

    
     

声明切面表达式:在实际的开发中切面表达式可能被多个通知 重复利用,所以如果同意在一处声明就可能不用那么麻烦的去书写了
示例:

/**
	 * 定义一个方法, 用于声明切入点表达式. 一般地, 该方法中再不需要添入其他的代码. 
	 * 使用 @Pointcut 来声明切入点表达式. 
	 * 后面的其他通知直接使用方法名来引用当前的切入点表达式. 
	 */
	@Pointcut("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")
	public void declareJointPointExpression(){}
	
	/**
	 * 在 com.atguigu.spring.aop.ArithmeticCalculator 接口的每一个实现类的每一个方法开始之前执行一段代码
	 */
	@Before("declareJointPointExpression()")
	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));
	}
	

  

原文地址:https://www.cnblogs.com/jeremy-blog/p/4054841.html