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

这篇文章主要介绍了@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); } }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持0133技术站。

以上就是浅谈@Aspect@Order各个通知的执行顺序的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » Java