springboot(十二)AOP的使用

x33g5p2x  于2021-12-17 转载在 其他  
字(3.0k)|赞(0)|评价(0)|浏览(583)

概述:

      说起AOP就不得不说下OOP了,OOP中引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。但是,如果我们需要为部分对象引入公共部分的时候,OOP就会引入大量重复的代码。例如:日志功能。

AOP技术利用一种称为“横切”的技术,解剖封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,这样就能减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。
 

springboot集成AOP:

新建项目:springboot-aop,pom.xml

  1. <dependencies>
  2. <!--aop-->
  3. <dependency>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-starter-aop</artifactId>
  6. </dependency>
  7. <!--web-->
  8. <dependency>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-web</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-test</artifactId>
  15. <scope>test</scope>
  16. </dependency>
  17. </dependencies>

新建web层测试接口:TestController.java

  1. @RestController
  2. public class TestController {
  3. private final static Logger logger=LoggerFactory.getLogger(TestController.class);
  4. @GetMapping("/test")
  5. public String test(String name){
  6. logger.info("进入controller test方法");
  7. return "name:"+name;
  8. }
  9. }

新建切面类:TestAspect.java,实现web层的日志切面

  1. @Aspect
  2. @Component
  3. public class TestAspect {
  4. private final static Logger logger= LoggerFactory.getLogger(TestAspect.class);
  5. /**
  6. * 指定切点
  7. */
  8. @Pointcut("execution(public * com.example.springbootaop.controller.TestController.*(..))")
  9. public void webLog(){}
  10. /**
  11. * 前置通知:方法调用前被调用
  12. * @param joinPoint
  13. */
  14. @Before("webLog()")
  15. public void doBefore(JoinPoint joinPoint){
  16. logger.info("doBefore 方法执行之前");
  17. Signature signature = joinPoint.getSignature();
  18. //获取request
  19. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
  20. HttpServletRequest request = attributes.getRequest();
  21. //url
  22. logger.info("url={}",request.getRequestURI());
  23. //method
  24. logger.info("method={}",request.getMethod());
  25. //ip
  26. logger.info("ip={}",request.getRemoteAddr());
  27. //代理类
  28. logger.info("代理类:"+signature.getDeclaringTypeName());
  29. //代理类法
  30. logger.info("代理类方法:"+signature.getName());
  31. //请求参数名称
  32. MethodSignature methodSignature = (MethodSignature) signature;
  33. String[] parameterNames = methodSignature.getParameterNames();
  34. logger.info("parameterNames={}", Arrays.toString(parameterNames));
  35. //请求参数值
  36. logger.info("parameterValues={}", Arrays.toString(joinPoint.getArgs()));
  37. }
  38. /**
  39. * 后置通知:方法调用后被调用
  40. */
  41. @After("webLog()")
  42. public void doAfter(){
  43. logger.info("doAfter:方法执行之后");
  44. }
  45. /**
  46. * 获取返回值
  47. * @param object
  48. */
  49. @AfterReturning(returning = "object",pointcut = "webLog()")
  50. public void doAfterReturning(Object object){
  51. logger.info("response={}",object);
  52. }
  53. }

  注:@Component 注解把类给ioc容器管理

@Aspect 注解 标明为切面类

@Pointcu t注解 定义的切入点

@Before 注解 切入点的前置通知

@After 注解 切入点的后置通知

@AfterReturning 注解 记录请求返回的对象。

测试:

启动项目,访问 localhost:8080/test?name=zhangsan

执行顺序:访问test接口---> 前置通知(doBefore) ---> 切入点方法(controller test方法) --> 后置通知(doAfter) --> 请求返回的对象(doAfterReturning)

**源码地址:**https://gitee.com/xu0123/springboot2

相关文章