浅谈@Aspect@Order各个通知的执行顺序

 更新时间:2022年02月14日 11:37:43   作者:快乐妮子  
这篇文章主要介绍了@Aspect@Order各个通知的执行顺序,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

@Aspect@Order各个通知的执行顺序

两个切面类:【记录日志】和【判断参数】,分别对应顺序 @Order(0) 和@Order(1) 。

本文只是将重点说下 执行顺序 这么回事哈哈哈

代码

【业务类】

/**
 * 登录控制器
 */
@Controller
public class LoginController {
    //向外面抛出异常
    public void loginWithThrow(String username, String password) throws Exception {
        if (username == null || password == null) {
            throw new Exception("登录信息不可为空啊");
        }
        System.out.println("LoginController#login...");
    }
    //抛出异常自己捕获的情况
    public void loginWithTryCatch(String username, String password) {
       try{
           if (username == null || password == null) {
               throw new Exception("登录信息不可为空啊");
           }
           System.out.println("LoginController#login...");
       }catch (Exception e){
           e.printStackTrace();
       }
    }
}

【切面类】

/**
 * 输出日志注解
 */
@Order(0)
@Aspect
@Component
public class LogAspect {
    //抽出共通的execution用的
    //com.yuki.demo.aop.aspect 包或者子包下所有类的方法
    @Pointcut("execution(* com.yuki.demo.aop.aspect..*.*(..))")
    public void pointcut(){
    }
    //前置通知
//    @Before("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
    @Before("pointcut()")
    public void before() {
        System.out.println("LogAspect#before...");
    }
    //环绕通知
    //ProceedingJoinPoint 只有环绕通知有
    @Around("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("LogAspectA#around开始...");
        //代理方法的执行,如果没有joinPoint.proceed() ,则前置通知@Before 不会执行,其它的通知正常
        joinPoint.proceed();
        //执行方法之后,如果joinPoint.proceed() 抛出了异常,则该句不会执行,抛出异常后直接跳出了aroud方法了
        System.out.println("LogAspectA#around结束...");
    }
    //后置通知(只要连接点被执行,不管是否抛出异常)
    @After("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
    public void after() {
        System.out.println("LogAspect#after...");
    }
    //异常通知(只有在joinPoint.proceed()方法执行向外面抛出了异常,才会执行该通知)
    @AfterThrowing("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
    public void afterThrowing() {
        System.out.println("LogAspect#afterThrowing...");
    }
    //正常的返回通知通知(正常结束了才会执行该通知)
    @AfterReturning("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
    public void afterReturning() {
        System.out.println("LogAspect#afterReturning...");
    }
}

【切面类】

/**
 * 判断请求参数的sign是否正确的 切面类
 */
@Order(1)
@Aspect
@Component
public class SignAspect {
    @Around("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("SignAspect#around开始...");
        joinPoint.proceed();
        System.out.println("SignAspect#around结束...");
    }
}

【启动配置】

省略。。。非重点

【测试类】

@SpringBootTest
class AopApplicationTests {
    @Autowired
    private LoginController loginController;
    @Test
    void contextLoads() {
        loginController.loginWithTryCatch("yuki", "1234");
    }
}

【控制台输出】

LogAspectA#around开始...
LogAspect#before...
SignAspect#around开始...
LoginController#login...
SignAspect#around结束...
LogAspectA#around结束...
LogAspect#after...
LogAspect#afterReturning...

小结

spring AspectJ order(顺序)

@Aspect
@Order(2)
public class HelloWorldAspectAnnotation {
	/**
	 * JoinPoint接口
	 * @param joinPoint
	 */
	/*public interface JoinPoint {
	    String toString();         //连接点所在位置的相关信息
	    String toShortString();     //连接点所在位置的简短相关信息
	    String toLongString();     //连接点所在位置的全部相关信息
	    Object getThis();         //返回AOP代理对象
	    Object getTarget();       //返回目标对象
	    Object[] getArgs();       //返回被通知方法参数列表
	    Signature getSignature();  //返回当前连接点签名
	    SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
	    String getKind();        //连接点类型
	    StaticPart getStaticPart(); //返回连接点静态部分
	}*/	
	
    //定义前置通知,注意这里是sayHello2
	//使用@Before进行前置通知声明,其中value用于定义切入点表达式或引用命名切入点
	@Before(value="execution(* com.boventech..*.sayHello2(..))&& args(param)",argNames="param")
	public void beforeAdvice(JoinPoint joinPoint,String param) {
		System.out.println(1);
		System.out.println("=======================");
		System.out.println("===param:" + param);
		System.out.println("=======================");
		System.out.println(joinPoint.getArgs().length);
		System.out.println("=======================");
		System.out.println(joinPoint.toString());
		System.out.println("=======================");
		System.out.println(joinPoint.getTarget());
		System.out.println("=======================");
		System.out.println(joinPoint.getThis());
		System.out.println("=======================");
		System.out.println("===========before advice");
	}
	/*value:指定切入点表达式或命名切入点;
    pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;*/
	@AfterReturning(value="execution(* com.boventech..*.sayHello2(..))&& args(param)",argNames="param",pointcut="execution(* com.boventech..*.sayHello2(..))&& args(param)")
	public void afterFinallyAdvice(JoinPoint joinPoint,String param) {
		System.out.println("param:"+param);
		System.out.println("===========");
		System.out.println("===========after finally advice");
	}
}
@Aspect
@Order(1)
public class HelloWorldAspectAnnotation2 {
	/**
	 * JoinPoint接口
	 * @param joinPoint
	 */
	/*public interface JoinPoint {
	    String toString();         //连接点所在位置的相关信息
	    String toShortString();     //连接点所在位置的简短相关信息
	    String toLongString();     //连接点所在位置的全部相关信息
	    Object getThis();         //返回AOP代理对象
	    Object getTarget();       //返回目标对象
	    Object[] getArgs();       //返回被通知方法参数列表
	    Signature getSignature();  //返回当前连接点签名
	    SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
	    String getKind();        //连接点类型
	    StaticPart getStaticPart(); //返回连接点静态部分
	}*/	
	
    //定义前置通知,注意这里是sayHello2
	//使用@Before进行前置通知声明,其中value用于定义切入点表达式或引用命名切入点
	@Before(value="execution(* com.boventech..*.sayHello2(..))&& args(param)",argNames="param")
	public void beforeAdvice(JoinPoint joinPoint,String param) {
		System.out.println(2);
		System.out.println("=======================");		
	}
	
	/*value:指定切入点表达式或命名切入点;
    pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;*/
	@AfterReturning(value="execution(* com.boventech..*.sayHello2(..))&& args(param)",argNames="param",pointcut="execution(* com.boventech..*.sayHello2(..))&& args(param)")
	public void afterFinallyAdvice(JoinPoint joinPoint,String param) {
		System.out.println("order:" + 2);
	}
}
public class AopAnnotationTest {	
	@Test
    public void testHelloworld() {
        ApplicationContext ctx =  new ClassPathXmlApplicationContext("/helloWorld2.xml");
        IHelloWorld2Service helloworldService =ctx.getBean("helloWorld2Service", IHelloWorld2Service.class);
        String param = "12";
        helloworldService.sayHello2(param);
    } 
}
<aop:aspectj-autoproxy/>
	<bean id="helloWorld2Service" class="com.boventech.learning.serviceImpl.HelloWorld2ServiceImpl"/>
	
    <bean id="aspect"
             class="com.boventech.learning.aspect.HelloWorldAspectAnnotation"/>
             
    <bean id="aspect2"
             class="com.boventech.learning.aspect.HelloWorldAspectAnnotation2"/>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Springboot3整合Mybatis-plus3.5.3报错问题解决

    Springboot3整合Mybatis-plus3.5.3报错问题解决

    在日常学习springboot3相关的代码时,在使用 SpringBoot3 整合 MyBatisplus 时出现了一些问题,花了不少时间处理,这篇文章主要介绍了Springboot3整合Mybatis-plus3.5.3报错问题解决,需要的朋友可以参考下
    2023-11-11
  • JSON.toJSONString()空字段不忽略修改的问题

    JSON.toJSONString()空字段不忽略修改的问题

    这篇文章主要介绍了JSON.toJSONString()空字段不忽略修改的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • JAVA正则表达式校验qq号码的方法

    JAVA正则表达式校验qq号码的方法

    Java作为一种开发语言,有许多值得推荐的地方,但是它一直以来没有自带对正则表达式的支持。下面小编给大家带来了JAVA正则表达式校验qq号码的方法,需要的朋友参考下吧
    2018-04-04
  • Mybatis Mapper中多参数方法不使用@param注解报错的解决

    Mybatis Mapper中多参数方法不使用@param注解报错的解决

    这篇文章主要介绍了Mybatis Mapper中多参数方法不使用@param注解报错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教。
    2022-01-01
  • Spring Boot分离配置文件的多种方式总结

    Spring Boot分离配置文件的多种方式总结

    Spring Boot可以外部化程序配置,以便可以在不同环境中使用相同的应用程序代码;当然Spring Boot可以将配置文件进行拆分,以便于激活不同的运行环境,下面这篇文章主要给大家总结介绍了关于Spring Boot分离配置文件的多种方式,需要的朋友可以参考下
    2022-11-11
  • JavaWeb中转发与重定向的区别小结

    JavaWeb中转发与重定向的区别小结

    转发和重定向是JavaWeb中常用的两种页面跳转方式,它们在实现上有一些区别,本文主要介绍了JavaWeb中转发与重定向的区别小结,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • Java平闰年判断的方法总结

    Java平闰年判断的方法总结

    本篇文章给大家整理了Java平闰年判断的两种方法,大家在写程序的时候如果用的到参考下吧。
    2018-02-02
  • Java 实战项目之精美物流管理系统的实现流程

    Java 实战项目之精美物流管理系统的实现流程

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+SpringBoot+Vue+maven+Mysql实现一个精美的物流管理系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • SpringBoot工程中Spring Security应用实践记录流程分析

    SpringBoot工程中Spring Security应用实践记录流程分析

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。这篇文章主要介绍了SpringBoot工程中Spring Security应用实践,需要的朋友可以参考下
    2021-09-09
  • 高并发下restTemplate的错误分析方式

    高并发下restTemplate的错误分析方式

    这篇文章主要介绍了高并发下restTemplate的错误分析方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10

最新评论