iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >SpringBoot中如何使用Aop
  • 516
分享到

SpringBoot中如何使用Aop

2023-06-20 18:06:40 516人浏览 独家记忆
摘要

这篇文章将为大家详细讲解有关SpringBoot中如何使用aop,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。什么是aopAOP(Aspect OrientedProgramming):面向

这篇文章将为大家详细讲解有关SpringBoot中如何使用aop,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

什么是aop

AOP(Aspect OrientedProgramming):面向切面编程,面向切面编程(也叫面向方面编程),是目前软件开发中的一个热点,也是spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

使用场景

利用AOP可以对我们边缘业务进行隔离,降低无关业务逻辑耦合性。提高程序的可重用性,同时提高了开发的效率。一般用于日志记录,性能统计,安全控制,权限管理,事务处理,异常处理,资源池管理。使用场景

为什么需要面向切面编程

面向对象编程(OOP)的好处是显而易见的,缺点也同样明显。当需要为多个不具有继承关系的对象添加一个公共的方法的时候,例如日志记录、性能监控等,如果采用面向对象编程的方法,需要在每个对象里面都添加相同的方法,这样就产生了较大的重复工作量和大量的重复代码,不利于维护。面向切面编程(AOP)是面向对象编程的补充,简单来说就是统一处理某一“切面”的问题的编程思想。如果使用AOP的方式进行日志的记录和处理,所有的日志代码都集中于一处,不需要再每个方法里面都去添加,极大减少了重复代码。

技术要点

  • 通知(Advice)包含了需要用于多个应用对象的横切行为,完全听不懂,没关系,通俗一点说就是定义了“什么时候”和“做什么”。

  • 连接点(Join Point)是程序执行过程中能够应用通知的所有点。

  • 切点(Poincut)是定义了在“什么地方”进行切入,哪些连接点会得到通知。显然,切点一定是连接点。

  • 切面(Aspect)是通知和切点的结合。通知和切点共同定义了切面的全部内容——是什么,何时,何地完成功能。

  • 引入(Introduction)允许我们向现有的类中添加新方法或者属性。

  • 织入(Weaving)是把切面应用到目标对象并创建新的代理对象的过程,分为编译期织入、类加载期织入和运行期织入。

整合使用

导入依赖

在springboot中使用aop要导aop依赖

 <!--aop 切面-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-aop</artifactId>        </dependency>

注意这里版本依赖于spring-boot-start-parent父pom中的spring-boot-dependencies

编写拦截的bean

这里我们定义一个controller用于拦截所有请求的记录

@RestControllerpublic class AopController {    @RequestMapping("/hello")    public String sayHello(){        System.out.println("hello");        return "hello";    }}

定义切面

SpringBoot在使用切面的时候采用@Aspect注解对POJO进行标注,该注解表明该类不仅仅是一个POJO,还是一个切面容器

定义切点

切点是通过@Pointcut注解和切点表达式定义的。

@Pointcut注解可以在一个切面内定义可重用的切点。

由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且实际中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。如图是execution表达式的语法:

SpringBoot中如何使用Aop

execution表示在方法执行的时候触发。以“”开头,表明方法返回值类型为任意类型。然后是全限定的类名和方法名,“”可以表示任意类和任意方法。对于方法参数列表,可以使用“..”表示参数为任意类型。如果需要多个表达式,可以使用“&&”、“||”和“!”完成与、或、非的操作。

定义通知

通知有五种类型,分别是:

  • 前置通知(@Before):在目标方法调用之前调用通知

  • 后置通知(@After):在目标方法完成之后调用通知

  • 环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法

  • 返回通知(@AfterReturning):在目标方法成功执行之后调用通知

  • 异常通知(@AfterThrowing):在目标方法抛出异常之后调用通知

代码中定义了三种类型的通知,使用@Before注解标识前置通知,打印“beforeAdvice...”,使用@After注解标识后置通知,打印“AfterAdvice...”,使用@Around注解标识环绕通知,在方法执行前和执行之后分别打印“before”和“after”。这样一个切面就定义好了,代码如下:

@Aspect@Componentpublic class AopAdvice {    @Pointcut("execution (* com.shangguan.aop.controller.*.*(..))")    public void test() {    }    @Before("test()")    public void beforeAdvice() {        System.out.println("beforeAdvice...");    }    @After("test()")    public void afterAdvice() {        System.out.println("afterAdvice...");    }    @Around("test()")    public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {        System.out.println("before");        try {            proceedingJoinPoint.proceed();        } catch (Throwable t) {            t.printStackTrace();        }        System.out.println("after");    }}

运行结果

SpringBoot中如何使用Aop

案例场景

这里我们通过一个日志记录场景来完整的使用Aop切面业务层只需关心代码逻辑实现而不用关心请求参数和响应参数的日志记录

那么首先我们需要自定义一个全局日志记录的切面类GlobalLogAspect

然后在该类添加@Aspect注解,然后在定义一个公共的切入点(Pointcut),指向需要处理的包,然后在定义一个前置通知(添加@Before注解),后置通知(添加@AfterReturning)和环绕通知(添加@Around)方法实现即可

日志信息类

package cn.soboys.core;import lombok.Data;@Datapublic class LogSubject {        private String description;        private String username;        private String startTime;        private String spendTime;        private String url;        private String method;        private String ip;        private Object parameter;        private Object result;        private String city;        private String device;}

全局日志拦截

package cn.soboys.core;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.reflect.MethodSignature;import java.lang.reflect.Method;public class BaseAspectSupport {    public Method resolveMethod(ProceedingJoinPoint point) {        MethodSignature signature = (MethodSignature)point.getSignature();        Class<?> targetClass = point.getTarget().getClass();        Method method = getDeclaredMethod(targetClass, signature.getName(),                signature.getMethod().getParameterTypes());        if (method == null) {            throw new IllegalStateException("无法解析目标方法: " + signature.getMethod().getName());        }        return method;    }    private Method getDeclaredMethod(Class<?> clazz, String name, Class<?>... parameterTypes) {        try {            return clazz.getDeclaredMethod(name, parameterTypes);        } catch (NoSuchMethodException e) {            Class<?> superClass = clazz.getSuperclass();            if (superClass != null) {                return getDeclaredMethod(superClass, name, parameterTypes);            }        }        return null;    }}

GlobalLogAspect

package cn.soboys.core;import cn.hutool.core.date.DateUtil;import cn.hutool.core.date.TimeInterval;import cn.hutool.JSON.jsONUtil;import cn.soboys.core.utils.HttpContextUtil;import io.swagger.annotations.apiOperation;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;import org.springframework.WEB.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestParam;import javax.servlet.http.httpservletRequest;import java.lang.reflect.Method;import java.lang.reflect.Parameter;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;@Slf4j@Aspect@Componentpublic class GlobalLogAspect extends BaseAspectSupport {        @Pointcut("execution(public * cn.soboys.mallapi.controller.*.*(..))")    public void log() {    }        @Around("log()")    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {        LogSubject logSubject = new LogSubject();        //记录时间定时器        TimeInterval timer = DateUtil.timer(true);        //执行结果        Object result = joinPoint.proceed();        logSubject.setResult(result);        //执行消耗时间        String endTime = timer.intervalPretty();        logSubject.setSpendTime(endTime);        //执行参数        Method method = resolveMethod(joinPoint);        logSubject.setParameter(getParameter(method, joinPoint.getArgs()));        HttpServletRequest request = HttpContextUtil.getRequest();        // 接口请求时间        logSubject.setStartTime(DateUtil.now());        //请求链接        logSubject.setUrl(request.getRequestURL().toString());        //请求方法GET,POST等        logSubject.setMethod(request.getMethod());        //请求设备信息        logSubject.setDevice(HttpContextUtil.getDevice());        //请求地址        logSubject.setIp(HttpContextUtil.getIpAddr());        //接口描述        if (method.isAnnotationPresent(ApiOperation.class)) {            ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);            logSubject.setDescription(apiOperation.value());        }        String a = JSONUtil.toJsonPrettyStr(logSubject);        log.info(a);        return result;    }        private Object getParameter(Method method, Object[] args) {        List<Object> argList = new ArrayList<>();        Parameter[] parameters = method.getParameters();        Map<String, Object> map = new HashMap<>();        for (int i = 0; i < parameters.length; i++) {            //将RequestBody注解修饰的参数作为请求参数            RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);            //将RequestParam注解修饰的参数作为请求参数            RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);            String key = parameters[i].getName();            if (requestBody != null) {                argList.add(args[i]);            } else if (requestParam != null) {                map.put(key, args[i]);            } else {                map.put(key, args[i]);            }        }        if (map.size() > 0) {            argList.add(map);        }        if (argList.size() == 0) {            return null;        } else if (argList.size() == 1) {            return argList.get(0);        } else {            return argList;        }    }}

关于SpringBoot中如何使用Aop就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: SpringBoot中如何使用Aop

本文链接: https://www.lsjlt.com/news/299410.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SpringBoot中如何使用Aop
    这篇文章将为大家详细讲解有关SpringBoot中如何使用Aop,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。什么是aopAOP(Aspect OrientedProgramming):面向...
    99+
    2023-06-20
  • 如何正确的使用SpringBoot AOP 拦截器
    本篇文章给大家分享的是有关如何正确的使用SpringBoot AOP 拦截器,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。常用用于实现拦截的有:Filter、HandlerIn...
    99+
    2023-05-31
    springboot aop 拦截器
  • 如何在SpringBoot中使用Spring-AOP实现接口鉴权
    目录面向切面编程AOP的底层原理实现AOP的相关术语相关注解以及切入点表达式实现接口鉴权1. 配置yml文件2. 读取账密配置3.编写接口鉴权方法4. 编写AOP5.编写接口测试面向...
    99+
    2024-04-02
  • SpringBoot项目怎么使用aop
    这篇“SpringBoot项目怎么使用aop”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SpringBoot项目怎么使用a...
    99+
    2023-07-05
  • SpringBoot如何使用RateLimiter通过AOP方式进行限流
    目录使用RateLimiter通过AOP方式进行限流1、引入依赖2、自定义注解3、AOP实现类4、使用SpringBoot之限流限流的基础算法Guava RateLimiter其他使...
    99+
    2024-04-02
  • 如何在PHP中使用AOP框架
    AOP(面向切面编程)是一种编程思想,用于解耦业务逻辑和横切关注点(如日志、权限等)。在PHP中,使用AOP框架可以简化编码,提高代码可维护性和可扩展性。本文将介绍在PHP中使用AOP框架的基本原理和实现方法。一、AOP的概念和原理面向切面...
    99+
    2023-05-19
    框架 PHP aop
  • Springboot如何使用Aspectj实现AOP面向切面编程
    目录要在 Springboot中声明 AspectJ 切面引入jar包       网上也有说要在application.properties...
    99+
    2024-04-02
  • 如何在Android中使用 AOP注解
    今天就跟大家聊聊有关如何在Android中使用 AOP注解,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、简介在Android 里面 注解主要用来干这么几件事:和编译器一起给你一些...
    99+
    2023-05-31
    android aop 注解
  • springboot如何使用AOP+反射实现Excel数据的读取
    这篇文章将为大家详细讲解有关springboot如何使用AOP+反射实现Excel数据的读取,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。如果我们遇到把excel表格中的数据导入到数据库,首...
    99+
    2023-06-29
  • Spring AOP如何在java项目中使用
    这篇文章将为大家详细讲解有关Spring AOP如何在java项目中使用 ,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、什么是AOP  AOP(Aspect Oriented ...
    99+
    2023-05-31
    java spring aop ava
  • SpringBoot项目使用aop案例详解
    目录前言一、SpringBoot项目引入AOP依赖二、普通方式三、注解方式前言 IOC和AOP是Spring中的两个核心的概念,简单介绍一下我的理解: IOC:控制反转,就是将以前由...
    99+
    2023-05-14
    SpringBoot使用aop SpringBoot项目使用aop
  • 解析SpringBoot中使用LoadTimeWeaving技术实现AOP功能
    目录1.SpringBoot AOP功能1.1 LTW与不同的切面织入时机1.2 JDK实现LTW的原理1.3 如何在Spring中实现LTW2. Springboot中使用LTW实...
    99+
    2024-04-02
  • 在springboot中使用AOP进行全局日志记录
    目录前言1、 spring AOP 是什么?2、spring AOP 能做什么?3、spring AOP 我能用 AOP 解决什么问题?一、引入依赖,增加自定义注解1、引入 mave...
    99+
    2024-04-02
  • 使用Spring Aop如何配置xml
    本篇文章给大家分享的是有关使用Spring Aop如何配置xml,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。AOP的配置方式有2种方式:xml配置和AspectJ注解方式。今...
    99+
    2023-05-31
    springaop xml
  • springboot中如何使用redis
    这篇文章将为大家详细讲解有关springboot中如何使用redis,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。正文很多时候,我们会在springboot中配置redis,但是就那么几个配置就配好了,没...
    99+
    2023-05-30
    springboot redis
  • SpringBoot中如何使用Servlet
    今天小编给大家分享一下SpringBoot中如何使用Servlet的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1.方式一(...
    99+
    2023-07-02
  • SpringBoot如何使用AOP实现统计全局接口访问次数
    本篇内容主要讲解“SpringBoot如何使用AOP实现统计全局接口访问次数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot如何使用AOP实现统计全局接口访问次数”吧!AOP是...
    99+
    2023-07-02
  • 如何在不使用spring框架中使用aop的功能
    目录spring提供了两种方式的AOP使用使用xml配置方式使用注解方式AspectJ简介AspectJ的使用实例不使用spring的aop功能实现日志输出第一种第二种:通过面向接口...
    99+
    2024-04-02
  • 使用SpringBoot怎么对Spring AOP进行集成
    今天就跟大家聊聊有关使用SpringBoot怎么对Spring AOP进行集成,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。需要的jar包添加到工程里。新增Maven依赖如下:<...
    99+
    2023-05-31
    springboot spring aop
  • SpringBoot开发怎么使用AOP记录日志
    这篇文章主要讲解了“SpringBoot开发怎么使用AOP记录日志”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringBoot开发怎么使用AOP记录日志”吧!为什么要用AOP?答案是解...
    99+
    2023-06-25
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作