65 切面AOP

news2024/11/28 3:33:56

65 切面AOP

切面基础概念

  • AOP:Aspect Oriented Programming,面向切面编程。是通过预编译方式(aspectj)或者运行期动态代理(Spring)实现程序功能的统一维护的技术。

面试问题:
Spring的两大核心是什么:IoC和AOP
分别有什么作用
IoC:控制反转,目的用于解耦,底层使用的技术是反射+工厂模式
AOP:面向切面编程,目的是在不修改目标对象源码的情况下,进行功能增强,底层使用的是动态代理技术

  • AOP作用:不修改源码的情况下,进行功能增强,通过动态代理实现的;
  • AOP的底层是通过动态代理实现的。在运行期间,通过代理技术动态生成代理对象,代理对象方法执行时进行功能的增强介入,再去调用目标方法,从而完成功能增强。
  • 常用的动态代理技术有:
    • JDK的动态代理:基于接口实现的
    • cglib的动态代理:基于子类实现的
  • Spring的AOP采用了哪种代理方式?
    • 如果目标对象有接口,就采用JDK的动态代理技术
    • 如果目标对象没有接口,就采用cglib技术
  • AOP相关概念

    • 目标对象(Target):要代理的/要增强的目标对象。

    • 代理对象(Proxy):目标对象被AOP织入增强后,就得到一个代理对象

    • 连接点(JoinPoint):能够被拦截到的点,在Spring里指的是方法。能增强的方法

    • 切入点(PointCut):要对哪些连接点进行拦截的定义。要增强的方法

    • 通知/增强(Advice):拦截到连接点之后要做的事情。如何增强,额外添加上去的功能和能力

    • 切面(Aspect):是切入点和通知的结合。 告诉Spring的AOP:要对哪个方法,做什么样的增强

    • 织入(Weaving):把增强/通知 应用到 目标对象来创建代理对象的过程
      在这里插入图片描述

  • AOP通知类型

    • @Before 前置通知 通知方法会在目标方法之前执行
    • @After 后置通知 通知方法会在目标方法之后执行
    • @Around 环绕通知 可以在目标方法之前和之后执行,可以更改方法执行之后的结果,自主性最大,需要掌握
    • @AfterReturning 通知方法将在目标方法正常结束之后执行
    • @AfterThrowing 通知方法会在目标方法爆出异常之后执行

切面应用

为了更好对AOP的使用有更深的了解,这里我们以下面这个场景进行实现:

现在在项目中有一些接口需要进行权限校验,即某些用户是无权访问这个接口的,如果无权限应进行拦截。同时这个接口很重要,应该避免某些人员进行恶意的刷接口,所以我们需要对这个接口进行防刷。对某些恶意刷的IP进行封禁,并进行限流,请你基于AOP来完成这个功能。

完整代码请查看:点击查看

注解

那么我们首先就需要写一个注解,来标识这种需要进行处理的接口。

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckPermission {
    
}

这里介绍一下元注解的概念

@Retention

中文翻译为保留的意思,标明自定义注解的生命周期。

从编写Java代码到运行主要周期为源文件→ Class文件 → 运行时数据,@Retention则标注了自定义注解的信息要保留到哪个阶段,分别对应的value取值为SOURCE →CLASS→RUNTIME。

  1. SOURCE 源代码java文件,生成的class文件中就没有该信息了
  2. CLASS class文件中会保留注解,但是jvm加载运行时就没有了
  3. RUNTIME 运行时,如果想使用反射获取注解信息,则需要使用RUNTIME,反射是在运行阶段进行反射的
  4. 示例:当RentionPolicy取值为SOURCE时,Class文件中不会保留注解信息,而取值为CLASS时,Class反编译文件中则保留了注解的信息
  1. Source:一个最简单的用法,就是自定义一个注解例如@ThreadSafe,用来标识一个类时线程安全的,就和注释的作用一样,不过更引人注目罢了。
  2. Class:这个有啥用呢?个人觉得主要是起到标记作用,还没有做实验,例如标记一个@Proxy,JVM加载时就会生成对应的代理类。
  3. Runtime:反射实在运行阶段执行的,那么只有Runtime的生命周期才会保留到运行阶段,才能被反射读取,也是我们最常用的。
@Target

中文翻译为目标,描述自定义注解的使用范围,允许自定义注解标注在哪些Java元素上(类、方法、属性、局部属性、参数…)

在这里插入图片描述

切面

/**
 * @FileName SecurityAspect
 * @Description 权限校验 限流 防刷 AOP切面
 * @Author yaoHui
 * @date 2024-10-09
 **/
@Aspect
@Slf4j
@Component
public class SecurityAspect {

    // 用于记录每个IP的请求时间戳,用于限流
    private Map<String, List<Long>> requestTimestamps = new ConcurrentHashMap<>();

    // 用于封禁IP的列表
    private Set<String> bannedIps = ConcurrentHashMap.newKeySet();

    // 限流阈值
    private static final int MAX_REQUESTS = 10;  // 最多允许的请求次数
    private static final long TIME_WINDOW_MS = 10 * 1000; // 时间窗口,10秒

    // 切入点 指定被注解CheckPermission标记的就是连接点
    @Pointcut("@annotation(com.fang.screw.communal.annotation.CheckPermission)")
    public void checkPermission(){

    }

    /***
    * @Description 对连接点进行业务扩展 进行鉴权 限流 防刷等操作
    * @param proceedingJoinPoint
    * @return {@link Object }
    * @Author yaoHui
    * @Date 2024/10/9
    */
    @Around("checkPermission()")
    public Object doPermissionCheck(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String ipAddress = request.getRemoteAddr();
        UserPO userPO = CurrentUserHolder.getUser();

        // 检查IP是否被封禁
        if (bannedIps.contains(ipAddress)) {
            return R.failed("该IP已被封禁,请稍后再试!");
        }

        // 非超级管理员不可以访问该接口
        if (userPO.getUserType() != 0){
            return R.failed("无访问权限!");
        }

        // 限流机制
        if (isRequestTooFrequent(ipAddress)) {
            bannedIps.add(ipAddress);  // 封禁该IP
            log.warn("IP {} 被封禁,因短时间内过多请求", ipAddress);
            return R.failed("请求过于频繁,请稍后再试!");
        }

        return proceedingJoinPoint.proceed();
    }

    /***
    * @Description 判断请求是否过于频繁
    * @param ipAddress
    * @return {@link boolean }
    * @Author yaoHui
    * @Date 2024/10/9
    */
    private boolean isRequestTooFrequent(String ipAddress) {
        long currentTime = System.currentTimeMillis();
        requestTimestamps.putIfAbsent(ipAddress, new ArrayList<>());
        List<Long> timestamps = requestTimestamps.get(ipAddress);

        timestamps.add(currentTime);

        // 清理超过时间窗口的请求
        timestamps.removeIf(timestamp -> currentTime - timestamp > TIME_WINDOW_MS);

        return timestamps.size() > MAX_REQUESTS;
    }
}

权限注解的使用

    /***
    * @Description 查询分类文章List
    * @return {@link PoetryResult<Map<Integer,List<ArticleVO>>> }
    * @Author yaoHui
    * @Date 2024/9/22
    */
    @CheckPermission
    @GetMapping("/getListSortArticle")
    public R<Map<Integer, List<ArticleVO>>> getListSortArticle() {
        return articleService.getListSortArticle();
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2201335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

上市公司企业平台生态嵌入数据(2001-2023年)

一、资料名称&#xff1a;2023-2001年上市公司企业平台生态嵌入数据 二、测算方式&#xff1a;参考C刊《管理学刊》陈南旭&#xff08;2024&#xff09;老师的做法&#xff0c;从上市公司年报中爬取“平台生态嵌入”的有关词频来衡量其嵌入程度具有可行性与科学性。 为更好地…

dfs +剪枝sudoku———poj2676

目录 前言 lowbit函数 数独 suduku 问题描述 输入 输出 问题分析 子网格位置 优化搜索顺序剪枝1 优化搜索顺序剪枝2 可行性剪枝 代码 前言 lowbit函数 这是一个利用二进制位运算取出二进制数最后一位’1‘的函数 数独 数独大家肯定都玩过&#xff0c;…

26届日常实习 momenta一面(牛客)

26届日常实习 momenta一面 八股问答sql 40min java的集合&#xff1a;list map set底层数据结构&#xff0c;特性&#xff0c;线程安全 get post区别 mysql跟redis以外你还知道哪些数据库&#xff1a;回答了大二参加大数据竞赛用的hive hbase 你觉得hbase链式存储的优势是什么…

与鸿蒙同行,Java Solon v3.0 正式发布(向下兼容)

与 HarmonyOS NEXT 10月8日公测同行。Solon &#xff08;开放原子开源基金会&#xff0c;孵化项目&#xff09; v3.0 正式发布&#xff0c; 且将在 2025 年启动华为编程语言 “仓颉” 版开发&#xff08;届时会有 Solon-Java 和 Solon-CJ 两大版本&#xff09;。本次大版本更新…

离散数学概述

离散数学概述 离散数学&#xff08;Discrete Mathematics&#xff09;是计算机科学、信息科学、数学等领域的基础学科之一。与连续数学&#xff08;如微积分&#xff09;不同&#xff0c;离散数学主要研究离散对象&#xff0c;如整数、图、逻辑公式等。在大学的课程中&#xf…

大学的离散数学:探索数学的逻辑之美

大学的离散数学&#xff1a;探索数学的逻辑之美 离散数学&#xff0c;作为数学的一个分支&#xff0c;它研究的是离散而非连续的对象。在大学课程中&#xff0c;离散数学是计算机科学、信息科学、电子工程等专业的重要基础课程。它不仅为学生提供了必要的数学工具&#xff0c;…

qt打包程序后运行提示缺少dll文件(使用官方打包程序)

qt打包程序后运行提示缺少dll文件(使用官方打包程序) 当使用Qt完成程序打包后&#xff0c;把程序生成的文件全部复制到另外的一台没有Qt开发环境的电脑上&#xff0c;双击运行.exe可执行程序&#xff0c;提示缺少一系列的.dll程序。 提示找不到 libstdc-6.dll libwinpthread-1…

算法.图论-bfs及其拓展

文章目录 广度优先搜索简介经典bfs习题地图分析贴纸拼词 01bfs解析基本过程相关习题 广度优先搜索简介 bfs的特点是逐层扩散, 从源头到目标点扩散了几层, 最短路就是多少 bfs的使用特征是任意两个节点的距离(权值)是相同的(无向图, 矩阵天然满足这一特点) bfs开始的时候可以是…

高性能缓存方案 —— Caffeine

一、简介 Caffeine是一个高性能的Java缓存库&#xff0c;它提供了本地缓存的功能。 Caffeine和Redis都是内存级别的缓存&#xff0c;为什么要使用在这两缓存作为二级缓存&#xff0c;它们两有什么区别呢? 虽然它们都是内存级别的缓存&#xff0c;但是Redis是需要单独部署的&…

DAY42WEB 攻防-PHP 应用MYSQL 架构SQL 注入跨库查询文件读写权限操作

一、PHP-MYSQL-SQL注入-常规查询 1.PHP-MYSQL-Web组成架构 MySQL(统一管理) ​ root&#xff08;自带默认&#xff09; ​ 网站A testA ​ 网站B testB MySQL(一对一管理) ​ testA用户 ​ 网站A testA ​ testB用户 ​ 网站B testB access无数据库用户 mysql里面有内置的管理…

使用 Stata 调用本地部署的大语言模型进行文本主要内容提取——历年政府工作报告中的经济增长目标提取

因此今天给大家分享一个新的方法。也就是通过部署在本地的大模型进行文本内容提取。 安装 Ollama 通过 Ollama 可以快速在本地部署一些常用的大模型。可以根据自己的系统从这里安装下载&#xff1a;https://github.com/ollama/ollama MacOS 下载 Ollama 链接: https://ollama…

计算机的错误计算(一百一十八)

摘要 探讨一个不动点的计算精度问题。 不动点是一类特殊的循环迭代。它有形式 例1. 已知迭代[1] 计算 显然&#xff0c;每个 均为 0.5 . 不妨在Visual Studio 2010 下用下列C语言代码计算&#xff1a; #include <stdio.h> #include <math.h>int main() {do…

Mac上功能全面,免费好用的解压缩工具

在日常使用Mac的过程中&#xff0c;相信不少朋友都有解压缩需求&#xff0c;目前存在的解压缩软件可以说各种各样&#xff0c;但是有的收费&#xff0c;有的解压速度慢&#xff0c;有的解压类型不全&#xff0c;各有优缺点&#xff0c;挑选起来眼花缭乱&#xff0c;挑来挑去也没…

西安凭借入驻企业展示科技“硬”实力的数字媒体产业园

在古城西安的怀抱中&#xff0c;一座以科技“硬”实力为核心竞争力的数字媒体产业园——西安国际数字影像产业园&#xff0c;正以其独特的魅力和无限的潜力&#xff0c;吸引着全球的目光。这里&#xff0c;不仅是数字创意的孵化场&#xff0c;更是科技创新的策源地。 西安国际数…

STM32 HAL库

1. 相关概念 1.1. 回调函数 Callback()回调函数与普通函数的本质区别在于调用者不同&#xff1a;普通函数由用户代码调用&#xff0c;而回调函数则是由系统在适当的条件下调用。回调函数用于对各种事件的响应和处理&#xff0c;如当指定的EXTI线上发生中断或事件时&#xff0…

windows基于MediaPipe 和 TensorFlow.js的3D手势检测

目录 流程总结 第一步&#xff1a;安装 Node.js 和 Yarn 1.安装 Node.js&#xff1a; 1.1 如果安装了其他版本不合适&#xff0c;可以安装调整nvm-setup.exe来调整 2.安装 Yarn&#xff1a; 第二步&#xff1a;克隆项目仓库 第三步&#xff1a;替换共享文件 1.删除旧的…

Java基本数据类型和String类型的转换

1.基本介绍 在程序开发中&#xff0c;我们经常需要将基本数据类型转换成String类型。或者将String类型转为基本数据类型。 2.基本类型转String类型 语法&#xff1a;将 基本数据类型的值 “” 即可 3.String类型转基本数据类型 语法&#xff1a;通过基本类型的包装类调用…

Web3与传统互联网的比较:机遇与挑战

随着科技的不断进步&#xff0c;Web3作为新一代互联网的概念逐渐浮出水面&#xff0c;改变了我们对网络的认知。相较于传统互联网&#xff0c;Web3在许多方面展现出不同的特征与潜力。本文将对Web3与传统互联网进行比较&#xff0c;探讨其带来的机遇与挑战。 一、核心概念的差异…

MySQL启动失败解决方案

目录 引言 一、查看/启动mysql服务的两种方式 方法一&#xff1a; 方法二&#xff1a; 二、修改mysql服务启动路径的地址 三、"my.ini"文件的使用 设置my.ini文件的路径 给出一个使用my.ini文件的小例子 引言 造成启动闪退\失败的原因我仅仅以个人查询的一下博…

Note24100901_Portal_V18_Advanced5_Modscan的Modbus仿真

Note24100901_Portal_V18_Advanced5_Modscan 的Modbus TCP/IP仿真 具体过程详见如下图片&#xff1a;![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/8d85098268484044b2816d8a78c031f4.png#pic_center 以上~