简介
本文用示例介绍Spring(SpringBoot)的AOP的执行顺序。
公共代码
Service
package com.example.demo.service; import com.example.demo.entity.User; public interface UserService { public void printUser(User user); }
package com.example.demo.service.impl; import com.example.demo.entity.User; import com.example.demo.service.UserService; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService { @Override public void printUser(User user) { if (user == null) { throw new RuntimeException("检查用户参数是否为空"); } System.out.print("id = " + user.getId()); System.out.print("\t userName = " + user.getUserName()); System.out.println("\t note = " + user.getNote()); } }
Controller
package com.example.demo.controller; import com.example.demo.annotation.OperationLog; import com.example.demo.entity.User; import com.example.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @RequestMapping("/user") @Controller public class UserController { @Autowired private UserService userService; @RequestMapping("/print") @ResponseBody public User testPrint(User user) { userService.printUser(user); return user; } @RequestMapping("/add") @ResponseBody @OperationLog(type = "添加", desc = "添加数据") public User testAdd(User user) { return user; } @RequestMapping("/update") @ResponseBody @OperationLog(type = "更新", desc = "更新数据") public User testUpdate(User user) { userService.printUser(user); return user; } }
启动类
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoSpringaopSimpleApplication { public static void main(String[] args) { SpringApplication.run(DemoSpringaopSimpleApplication.class, args); } }
Entity
package com.example.demo.entity; import lombok.Data; @Data public class User { private Integer id; private String userName; private String note; }
AOP类的顺序控制
可以用@Order来控制切面的执行顺序,当多个切面类都会执行时@Order里的值越小的越先执行。(也可以这样做:切面类实现org.springframework.core.Ordered接口,覆写getOrder()方法)。
AOP类1
package com.example.demo.aspect; import com.example.demo.annotation.OperationLog; import com.example.demo.common.util.JsonUtil; import com.example.demo.entity.User; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.lang.reflect.Method; @Aspect @Component @Order(1) public class SimpleAspect { @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))") public void pointCut() { } @Before("pointCut()") public void before() { System.out.println("####################### SimpleAspect.before #######################"); } @Around("pointCut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("####################### SimpleAspect.around #######################"); MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Method method = methodSignature.getMethod(); System.out.println("joinPoint.getTarget().toString() : " + joinPoint.getTarget().toString()); System.out.println("methodSignature.getName() : " + methodSignature.getName()); System.out.println("method.getName() : " + method.getName()); System.out.println("method.getReturnType().getName() : " + method.getReturnType().getName()); Object[] objects = joinPoint.getArgs(); System.out.println(JsonUtil.toJson(objects)); System.out.println("------------------- SimpleAspect.around: around before -------------------"); Object object = joinPoint.proceed(); System.out.println("------------------- SimpleAspect.around: 返回值 -------------------"); System.out.println(JsonUtil.toJson(object)); System.out.println("------------------- SimpleAspect.around: around after -------------------"); return object; } @After("pointCut()") public void after() { System.out.println("####################### SimpleAspect.after #######################"); } @AfterReturning("pointCut()") public void afterReturning() { System.out.println("####################### SimpleAspect.afterReturning #######################"); } @AfterThrowing("pointCut()") public void afterThrowing() { System.out.println("####################### SimpleAspect.afterThrowing #######################"); } }
AOP类2
package com.example.demo.aspect; import com.example.demo.common.util.JsonUtil; import com.example.demo.entity.User; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.lang.reflect.Method; @Aspect @Component @Order(2) public class OrderTestAspect { @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))") public void pointCut() { } @Before("pointCut()") public void before() { System.out.println("####################### OrderTestAspect.before #######################"); } @Around("pointCut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("####################### OrderTestAspect.around #######################"); MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Method method = methodSignature.getMethod(); System.out.println("joinPoint.getTarget().toString() : " + joinPoint.getTarget().toString()); System.out.println("methodSignature.getName() : " + methodSignature.getName()); System.out.println("method.getName() : " + method.getName()); System.out.println("method.getReturnType().getName() : " + method.getReturnType().getName()); Object[] objects = joinPoint.getArgs(); System.out.println(JsonUtil.toJson(objects)); System.out.println("------------------- OrderTestAspect.around: around before -------------------"); Object object = joinPoint.proceed(); System.out.println("------------------- OrderTestAspect.around: 返回值 -------------------"); System.out.println(JsonUtil.toJson(object)); System.out.println("------------------- OrderTestAspect.around: around after -------------------"); return object; } @After("pointCut()") public void after() { System.out.println("####################### OrderTestAspect.after #######################"); } @AfterReturning("pointCut()") public void afterReturning() { System.out.println("####################### OrderTestAspect.afterReturning #######################"); } @AfterThrowing("pointCut()") public void afterThrowing() { System.out.println("####################### OrderTestAspect.afterThrowing #######################"); } }
测试
后端结果
####################### SimpleAspect.around ####################### joinPoint.getTarget().toString() : com.example.demo.service.impl.UserServiceImpl@1d6f5d26 methodSignature.getName() : printUser method.getName() : printUser method.getReturnType().getName() : void [{"id":321,"userName":"Tony","note":"abc"}] ------------------- SimpleAspect.around: around before ------------------- ####################### SimpleAspect.before ####################### ####################### OrderTestAspect.around ####################### joinPoint.getTarget().toString() : com.example.demo.service.impl.UserServiceImpl@1d6f5d26 methodSignature.getName() : printUser method.getName() : printUser method.getReturnType().getName() : void [{"id":321,"userName":"Tony","note":"abc"}] ------------------- OrderTestAspect.around: around before ------------------- ####################### OrderTestAspect.before ####################### id = 321 userName = Tony note = abc ####################### OrderTestAspect.afterReturning ####################### ####################### OrderTestAspect.after ####################### ------------------- OrderTestAspect.around: 返回值 ------------------- null ------------------- OrderTestAspect.around: around after ------------------- ####################### SimpleAspect.afterReturning ####################### ####################### SimpleAspect.after ####################### ------------------- SimpleAspect.around: 返回值 ------------------- null ------------------- SimpleAspect.around: around after -------------------
可以发现,优先级高的,before先执行,after后执行。
AOP方法的顺序控制
有人说:单个AOP类里边,可以用@Order来控制方法的执行顺序。但是,我测试是不可以的!
AOP类
package com.example.demo.aspect; import com.example.demo.annotation.OperationLog; import com.example.demo.common.util.JsonUtil; import com.example.demo.entity.User; import com.sun.org.apache.regexp.internal.RE; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.lang.reflect.Method; @Aspect @Component public class SimpleAspect { @Order(2) @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))") public void pointCut1() { } @Order(1) @Pointcut("@annotation(com.example.demo.annotation.OperationLog)") public void pointCut2() { } @Before("pointCut1()") public void before1() { System.out.println("############################ SimpleAspect.before 1 ############################"); } @Before("pointCut2()") public void before2() { System.out.println("############################ SimpleAspect.before 2 ############################"); } }
Service类
package com.example.demo.service.impl; import com.example.demo.annotation.OperationLog; import com.example.demo.entity.User; import com.example.demo.service.UserService; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService { @Override @OperationLog public void printUser(User user) { if (user == null) { throw new RuntimeException("检查用户参数是否为空"); } System.out.print("id = " + user.getId()); System.out.print("\t userName = " + user.getUserName()); System.out.println("\t note = " + user.getNote()); } }
测试
访问:http://localhost:8080/doc.html
结果:(没有按照执行的顺序执行)
############################ SimpleAspect.before 1 ############################ ############################ SimpleAspect.before 2 ############################
请先
!