zoukankan      html  css  js  c++  java
  • SpringAOP自定义注解应用

    一、AOP简述

    什么是aop?

    AOP 即 Aspect Oriented Program 面向切面编程

    与OOP对比,AOP是处理一些横切行问题。这些横切性问题不会影响到主逻辑的实现,但是会散落到代码的各个部分,难以维护。AOP就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的。

     传统OOP是自上而下的逻辑开发如图1,AOP是一种面向切面的编程思想。这些横切性问题,把它们抽象为一个切面,关注点在切面的编程如图2。

      图1                   图2

    如果说 IoC 是 Spring 的核心,那么面向切面编程就是 Spring 最为重要的功能之一了,在数据库事务中切面编程被广泛使用。

    首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能。

    • 所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务
    • 所谓的周边功能,比如性能统计,日志,事务管理等等

    周边功能在 Spring 的面向切面编程AOP思想里,即被定义为切面

    在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发,然后把切面功能和核心业务功能 "编织" 在一起,这就叫AOP

    AOP 的目的

    AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码降低模块间的耦合度,并有利于未来的可拓展性和可维护性

    Spring AOP应用场景

    日志记录,权限验证,效率检查,事务管理......

    AOP 当中的概念:

    • 切入点(Pointcut)
      在哪些类,哪些方法上切入(where
    • 通知(Advice)
      在方法执行的什么实际(when:方法前/方法后/方法前后)做什么(what:增强的功能)
    • 切面(Aspect)
      切面 = 切入点 + 通知,通俗点就是:在什么时机,什么地方,做什么增强!
    • 织入(Weaving)
      把切面加入到对象,并创建出代理对象的过程。(由 Spring 来完成)

    注:开发AOP有两种方式1、注解开发 2、xml配置开发 此处只对注解开发做详细笔记。

    二、使用注解来开发 Spring AOP

    选择连接点

    Spring 是方法级别的 AOP 框架,我们主要也是以某个类额某个方法作为连接点,另一种说法就是:选择哪一个类的哪一方法用以增强功能。

    @GetMapping(value = "/test1")
        public String test1(HttpServletRequest request, String var1) {
            LOG.info("============打印日志开始============");
            LOG.info("URL: " + request.getRequestURL().toString());
            LOG.info("============打印日志结束============");
            return "test1";
        }

    创建切面

    @Aspect
    @Component
    @Log4j2
    //@Profile("dev") //指定dev环境该注解有效,其他环境无效(未测试)
    public class DemoAspect {
        private static final Logger logger = LoggerFactory.getLogger(DemoAspect.class);
    
        /**
         * 切入点
         *
         * @Pointcut("@annotation(cn.van.annotation.annotation.WebLog)")
         **/
    
        @Pointcut("execution(public * com.example.demo2.controller.*.*(..))")
        public void addAdvice() {
        }
    
        @Before("addAdvice()")
        public void before(JoinPoint joinPoint) {
            Object[] args = joinPoint.getArgs();
            HttpServletRequest requests = (HttpServletRequest) args[0];
            log.info("============打印日志开始============");
            log.info("URL: " + requests.getRequestURL().toString());
            log.info("============打印日志结束============");
    //        LOG.info("before....");
        }
    
    }
    选择好了连接点就可以创建切面了,我们可以把切面理解为一个拦截器,当程序运行到连接点的时候,被拦截下来,在 Spring 中只要使用 @Aspect 注解一个类,那么 Spring IoC 容器就会认为这是一个切面了。
    注:被定义为切面的类仍然是一个 Bean ,需要 @Component 注解标注。
    Spring中AspectJ注解如下:
    1. @Before 前置通知,在连接点方法前调用
    2. @Around 环绕通知,它将覆盖原有方法,但是允许你通过反射调用原有方法,后面会讲
    3. @After 后置通知,在连接点方法后调用
    4. @AfterReturning 返回通知,在连接点方法执行并正常返回后调用,要求连接点方法在执行过程中没有发生异常
    5. @AfterThrowing 异常通知,当连接点方法异常时调用

    定义切点

    切面中用到的@Pointcut注解即为切入点。
    @Pointcut("execution(public * com.example.demo2.controller.*.*(..))")

    环绕通知

    这是 Spring AOP 中最强大的通知,因为它集成了前置通知和后置通知,它保留了连接点原有的方法的功能,所以它及强大又灵活。如下代码:

     //  使用 @Around 注解来同时完成前置和后置通知
        @Around("execution(* pojo.Landlord.service())")
        public void around(ProceedingJoinPoint joinPoint) {
            System.out.println("开始");
    
            try {
                joinPoint.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
    
            System.out.println("结束");
        }

    测试的结果为:

    开始
    业务层中进行的处理
    结束

    简单来说:环绕通知=前置+目标方法执行+后置通知,proceed方法就是用于启动目标方法执行的。

    ps:

    SpringBoot 配置 AOP 记录日志 可以通过切面的方式打印控制器层的日志,但是可能存在以下问题:

    不够灵活,由于是以所有 Controller 方法中的方法为切面,也就是说切死了,如果说我们不想让某个接口打印出入参日志,就办不到了;

    Controller 包层级过深时,导致很多包下的接口切不到。

    所以,可以通过指定某些方法打印日志,即通过自定义注解打印日志。

    AOP官网:AOP
     
  • 相关阅读:
    CSS hack
    字符串中常用的方法
    排序算法
    拾遗
    数组类型检测
    数组常用的方法
    go 文件服务器(标准库) 添加关机,睡眠,退出功能
    go cmd 交互 初始化执行某些命令
    go 内网IP及外网IP获取
    go 快排实现
  • 原文地址:https://www.cnblogs.com/wmy666/p/13045125.html
Copyright © 2011-2022 走看看