浅谈@Aspect@Order各个通知的执行顺序
作者:快乐妮子 时间:2021-10-24 19:00:38
@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"/>
来源:https://blog.csdn.net/u014240299/article/details/103912843
标签:@Aspect,@Order,通知,执行顺序
0
投稿
猜你喜欢
从java源码分析线程池(池化技术)的实现原理
2021-12-24 00:01:24
nacos注册中心单节点ap架构源码解析(最新推荐)
2022-09-02 09:31:43
Android app启动图适配方法实例
2023-07-31 16:23:34
java开源项目jeecgboot的超详细解析
2023-07-19 03:30:53
基于jdk动态代理和cglib动态代理实现及区别说明
2022-04-11 00:32:44
详解java开发webservice的几种方式
2023-03-13 04:31:33
Spring Security 实现短信验证码登录功能
2022-11-02 19:39:30
浅析SpringBoot2底层注解@Conditional@ImportResource
2023-08-01 23:35:51
springboot aop里的@Pointcut()的配置方式
2021-11-18 20:55:37
C# WORD操作实现代码
2023-11-20 05:16:25
浅析Android App的相对布局RelativeLayout
2023-04-08 18:28:48
Android实现Activity水平和垂直滚动条的方法
2021-07-04 13:06:06
英雄联盟辅助lol挂机不被踢的方法(lol挂机脚本)
2022-03-15 12:57:59
c++异常处理机制示例及详细讲解
2022-04-27 11:31:27
C#实现QQ聊天窗口
2023-07-06 02:43:56
C# Chart折线图使用鼠标滚轮放大、缩小和平移曲线方式
2022-09-01 07:07:39
Android实现闪光灯效果
2023-08-02 12:20:06
Spring Boot Actuator监控端点小结
2023-02-15 05:04:23
C#中使用XmlDocument类来创建和修改XML格式的数据文件
2023-09-19 16:33:45
Android对话框AlertDialog详解
2023-06-20 01:47:19