美文网首页Java
Java Spring-AOP切面的优先级和切点表达式

Java Spring-AOP切面的优先级和切点表达式

作者: 一亩三分甜 | 来源:发表于2020-01-31 22:35 被阅读0次

可以使用@Order注解指定切面的优先级,值越小优先级越高

在同一个连接点上应用不止一个切面时,除非明确指定,否则它们的优先级是不确定的。切面的优先级可以通过实现Ordered接口或利用@Order注解指定。

public interface ArithmeticCalculator {
    int add(int i, int j);
    int sub(int i, int j);
    int mul(int i, int j);
    int div(int i, int j);
}

@Component
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        return result;
    }

    @Override
    public int mul(int i, int j) {
        int result = i * j;
        return result;
    }

    @Override
    public int div(int i, int j) {
        int result = i / j;
        return result;
    }
}

//把这个类声明为一个切面:需要把该类放入到IOC容器中、再声明为一个切面
@Order(2)
@Aspect
@Component
public class LoggingAspect {

    //声明该方法是一个前置通知:在目标方法开始之前执行
    @Before("execution(public int com.cloud.spring.aop.impl.ArithmeticCalculator.*(int,int))")
    public void beforeMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("The method " + methodName + " begins with" + args);
    }

    //后置通知:在目标方法执行后(无论是否发生异常),执行的通知
    //在后置通知中还不能访问目标方法执行的结果
    @After("execution(* com.cloud.spring.aop.impl.*.*(int,int))")
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " ends");
    }

    /*
    * 在方法正常结束之后执行的代码
    * 返回通知是可以访问到方法的返回值的!
    */
    @AfterReturning(value = "execution(* com.cloud.spring.aop.impl.*.*(..))",returning = "result")
    public void afterReturing(JoinPoint joinPoint,Object result){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " ends with " + result);
    }
     /*
     *  在目标方法出现异常时会执行的代码
     *  可以访问到异常对象,且可以指定在出现特定异常时再执行通知代码
     */
    @AfterThrowing(value = "execution(* com.cloud.spring.aop.impl.*.*(..))",throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint,Exception ex){
        String  methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " occurs exception with " + ex);
    }

    /*
    * 环绕通知需要携带ProceedingJointPoint 类型的参数
    * 环绕通知类似于动态代理的全过程:ProceedingJointPoint 类型的参数可以决定是否执行目标方法。
    * 且环绕通知必须有返回值,返回值即为目标方法的返回值
    */
    @Around("execution(* com.cloud.spring.aop.impl.*.*(..))")
    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 Main {
    public static void main(String[] args) {
        //1.创建Spring的IOC容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.从IOC容器中获取bean的实例
        ArithmeticCalculator arithmeticCalculator = context.getBean(ArithmeticCalculator.class);
        //3.使用bean
        int result = arithmeticCalculator.add(3,6);
        System.out.println("result:" + result);

        result = arithmeticCalculator.div(9,3);
        System.out.println("result:" + result);
    }
}

@Order(1)
@Aspect
@Component
public class ValidationAspect {

    @Before("execution(public int com.cloud.spring.aop.impl.ArithmeticCalculator.*(..))")
    public void validateArgs(JoinPoint joinPoint){
        System.out.println("--> validate: " + Arrays.asList(joinPoint.getArgs()));
    }
}
//输出
Connected to the target VM, address: '127.0.0.1:51995', transport: 'socket'
--> validate: [3, 6]
The method add begins with [3, 6]
The method add begins with[3, 6]
The method add ends with 9
The method add ends 
The method add ends
The method add ends with 9
result:9
--> validate: [9, 3]
The method div begins with [9, 3]
The method div begins with[9, 3]
The method div ends with 3
The method div ends 
The method div ends
The method div ends with 3
result:3

重用切点表达式:定义一个方法,用于声明切入点表达式,一般地,该方法中再不需要填入其他的代码。使用Pointcut来声明切入点表达式。后面的其他通知直接使用方法名来引用当前的切入点表达式。

//把这个类声明为一个切面:需要把该类放入到IOC容器中、再声明为一个切面
@Order(2)
@Aspect
@Component
public class LoggingAspect {

    /*
    * 定义一个方法,用于声明切入点表达式。一般地,该方法中再不需要添入其他的代码。
    * 使用@Pointcut来声明切入点表达式
    * 后面的其他通知直接使用方法名来引用当前的切入点表达式
    */
    @Pointcut("execution(public int com.cloud.spring.aop.impl.ArithmeticCalculator.*(..))")
    public void declareJointPointExpression(){}

    //声明该方法是一个前置通知:在目标方法开始之前执行
    @Before("declareJointPointExpression()")
    public void beforeMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("The method " + methodName + " begins with" + args);
    }

    //后置通知:在目标方法执行后(无论是否发生异常),执行的通知
    //在后置通知中还不能访问目标方法执行的结果
    @After("declareJointPointExpression()")
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " ends");
    }

    /*
    * 在方法正常结束之后执行的代码
    * 返回通知是可以访问到方法的返回值的!
    */
    @AfterReturning(value = "declareJointPointExpression()",returning = "result")
    public void afterReturing(JoinPoint joinPoint,Object result){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " ends with " + result);
    }
     /*
     *  在目标方法出现异常时会执行的代码
     *  可以访问到异常对象,且可以指定在出现特定异常时再执行通知代码
     */
    @AfterThrowing(value = "declareJointPointExpression()",throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint,Exception ex){
        String  methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " occurs exception with " + ex);
    }

    /*
    * 环绕通知需要携带ProceedingJointPoint 类型的参数
    * 环绕通知类似于动态代理的全过程:ProceedingJointPoint 类型的参数可以决定是否执行目标方法。
    * 且环绕通知必须有返回值,返回值即为目标方法的返回值
    */
    @Around("declareJointPointExpression()")
    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;
    }
}
//输出
Connected to the target VM, address: '127.0.0.1:52041', transport: 'socket'
--> validate: [3, 6]
The method add begins with [3, 6]
The method add begins with[3, 6]
The method add ends with 9
The method add ends 
The method add ends
The method add ends with 9
result:9
--> validate: [9, 3]
The method div begins with [9, 3]
The method div begins with[9, 3]
The method div ends with 3
The method div ends 
The method div ends
The method div ends with 3
result:3

相关文章

  • Java Spring-AOP切面的优先级和切点表达式

    可以使用@Order注解指定切面的优先级,值越小优先级越高 在同一个连接点上应用不止一个切面时,除非明确指定,否则...

  • Spring-AOP

    spring-aop模块笔记 核心接口与概念 Pointcut切点:切点就是所有的待匹配的切入点,被它过滤通过的类...

  • 18、spring-AOP-切点表达式

    Spring切点表达式 一、概要 前面定义切点表达式时使用了execution表达式,其实execution就是一...

  • 说说 Spring 支持的 AspectJ 语法

    本文以 AspectJ5.0 为基础。 1 切点表达式 AspectJ5.0 的切点表达式由关键字和操作参数组成。...

  • aspectj注解方式创建切面

    切点切点是一个接口,切点表达式定义的方法(切点的方法)执行的时候触发通知切点不需要使用 aspectj注解声明,只...

  • Spring AOP 切点指示器

    Spring AOP借助AspectJ的切点表达式语言来定义Spring切面,下面是切点表达式中使用的指示器: e...

  • Spring AOP 简化笔记(一)

    切点表达式 编写配置 编写切点 编写切面(@Aspect注解)简化切面编码(@Pointcut注解)环绕通知(@A...

  • AOP源码分析--增强器查找

    *PonintCut切点查找,处理 根据pointcut的表达式,解析真正的切点。包括:方法,|,& 等的解析。由...

  • Java中运算符的优先级

    所谓优先级,就是在表达式中的运算顺序。Java 中常用的运算符的优先级如下表所示: 级别为 1 的优先级最高,级别...

  • Java 从入门到放弃 入门篇(控制程序流程一)

    Java 运算符 优先级;运算符的优先级决定存在多个运算符时一个表达式的计算顺序,最简单的规则就是乘法和除法在加减...

网友评论

    本文标题:Java Spring-AOP切面的优先级和切点表达式

    本文链接:https://www.haomeiwen.com/subject/ihunthtx.html