千家信息网

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

发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,小编给大家分享一下@Aspect@Order各个通知的执行顺序是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!@Asp
千家信息网最后更新 2025年01月19日@Aspect@Order各个通知的执行顺序是什么

小编给大家分享一下@Aspect@Order各个通知的执行顺序是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

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

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

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

    代码

    【业务类】

    /** * 登录控制器 */@Controllerpublic 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@Componentpublic 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@Componentpublic 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结束...");    }}

    【启动配置】

    省略。。。非重点

    【测试类】

    @SpringBootTestclass 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);    } }
                                         

    以上是"@Aspect@Order各个通知的执行顺序是什么"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

    0