关于注解执行优先级、同优先级情况下执行顺序

如果想要自定义注解按照想要的顺序来执行,可以通过在注解实现类里面使用@Order注解来指定优先级。
优先级逻辑是:优先级值越小,优先级越大;优先级值越大,优先级越小。
不设置优先级值。会有一个默认值:2147483647,也就是最小优先级。

注解执行顺序是:

优先级大的的前置通知先执行,然后到优先级小的的前置通知; 接着到优先级小的的后置通知,再到优先级大的的后置通知。(也就是优先级大的注解逻辑会把优先级小的注解逻辑包裹在内部)

官方说法:
The highest precedence advice runs first “on the way in” (so, given two pieces of before advice, the one with highest precedence runs first). “On the way out” from a join point, the highest precedence advice runs last

相同优先级值的情况下:我在网上查,GPT的回复是按照注解的声明顺序执行。

代码验证

创建三个优先级相同的注解:(三个注解的定义就只有打印的内容不同,只贴其中一个)

package org.jeecg.modules.test.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD) //作用范围
@Retention(RetentionPolicy.RUNTIME) //生效时期
public @interface Test1 {

}

package org.jeecg.modules.test.annotation;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @ClassName: Test1Aspect
 * @Author: 
 * @Date: 2023/11/1 10:40
 * @Description:
 **/
@Aspect
@Order(1)
@Component
public class Test1Aspect {
    @Pointcut("@annotation(org.jeecg.modules.test.annotation.Test1)")
	public void testPoint(){

    }
    @Before("testPoint()")
    public void around() throws Throwable {
	    System.out.println("测试1的注解执行前置通知");
    }
	@After("testPoint()")
	public void after() throws Throwable {
		System.out.println("测试1的注解执行后置通知");
	}
	@Around("testPoint()")
	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("测试1的注解执行环绕通知前置通知");
		Object proceed = joinPoint.proceed();
		System.out.println("测试1的注解执行环绕通知后置通知");
		return proceed;
	}
}


package org.jeecg.modules.test;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.test.annotation.Test1;
import org.jeecg.modules.test.annotation.Test2;
import org.jeecg.modules.test.annotation.Test3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: TestController
 * @Author: 
 * @Date: 2023/8/21 14:28
 * @Description:
 **/
@Slf4j
@RestController
@Api("测试")
public class TestController {

	@RequestMapping("/test")
	@ApiOperation("测试")
	@Test1()
	@Test2()
	@Test3()
	public Object test(String a){
		System.out.println("进入测试方法了");
		return "ok";
	}
}

运行结果(测了很多组,结果均如下)

关于注解执行优先级、同优先级情况下执行顺序_第1张图片

更改注解顺序
package org.jeecg.modules.test;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.test.annotation.Test1;
import org.jeecg.modules.test.annotation.Test2;
import org.jeecg.modules.test.annotation.Test3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: TestController
 * @Author:
 * @Date: 2023/8/21 14:28
 * @Description:
 **/
@Slf4j
@RestController
@Api("测试")
public class TestController {
	@Autowired
	private AsyncService asyncService;
	@Autowired
	private TestService testService;
	@Autowired
	private RedisTemplate redisTemplate;

	@RequestMapping("/test")
	@ApiOperation("测试")
	@Test3()
	@Test2()
	@Test1()
	public Object test(String a){
		System.out.println("进入测试方法了");
		return "ok";
	}
}

运行结果(测了很多组,结果都是如下)

关于注解执行优先级、同优先级情况下执行顺序_第2张图片

结论

优先级大的的前置通知先执行,然后到优先级小的的前置通知; 接着到优先级小的的后置通知,再到优先级大的的后置通知。(也就是优先级大的注解逻辑会把优先级小的注解逻辑包裹在内部)
执行顺序:

  1. order值小的环绕通知joinPoint.proceed();前面部分
  2. order值小的前置通知
  3. order值大的环绕通知joinPoint.proceed();前面部分
  4. order值大的前置通知
  5. order值大的后置置通知
  6. order值大的环绕通知joinPoint.proceed();后面面部分
  7. order值小的后置置通知
  8. order值小的环绕通知joinPoint.proceed();后面面部分

如果order值相同则按照在方法上面注解的先后顺序来执行,先放的相当于order值小,先执行。

你可能感兴趣的:(基础,springboot,java,spring)