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

网友投稿 393 2022-08-28


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

目录@Aspect@Order各个通知的执行顺序代码小结spring AspectJ 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("登录信viHeSuKepQ息不可为空啊");

}

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.ashttp://pect 包或者子包下所有类的方法

@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 {

Stringhttp:// 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);

}

}

class="com.boventech.learning.aspect.HelloWorldAspectAnnotation"/>

class="com.boventech.learning.aspect.HelloWorldAspectAnnotation2"/>

class="com.boventech.learning.aspect.HelloWorldAspectAnnotation"/>

class="com.boventech.learning.aspect.HelloWorldAspectAnnotation2"/>

class="com.boventech.learning.aspect.HelloWorldAspectAnnotation2"/>


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:python之内置函数all || 内置函数any(内置函数 python)
下一篇:python之warnings模块(warnings.filterwarnings(
相关文章

 发表评论

暂时没有评论,来抢沙发吧~