springAop讲解

news2024/11/20 4:41:39

写在前面

本文旨在帮助入门和了解aop的概念以及基本用法,如有错误请在评论区指出,万分感谢。
部分资料出自尚硅谷课堂笔记,改内容更好,更完善。

依赖准备

使用aop编程的话,我们需要先导入需要的依赖

  • spring-context: 包含Spring的核心功能和上下文支持。
  • spring-aop: 提供了面向切面编程的支持。

什么是代理?

二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。
在这里插入图片描述

举例:

杨超越是一个明星,她会唱歌和跳舞,她现在想要举办一场演唱会,那么需要场地的租用和场地搭建这个环境的准备,已经后续的拆除。此时对于这个演唱会核心的内容就是明星杨超越唱歌,跳舞,那么非核心的内容就是场地的搭建,拆除,租用等等,这时候对杨超越来说,我只会唱歌跳舞,这方面的我不会,所以此时就可以让他的经纪人去找负责对应业务的职员搭建和准备演唱会。那么这个经纪人就属于代理。核心业务是跳舞唱歌,非核心业务就是演唱会的相关筹办。 当我们需要对核心代码增加非核心业务的逻辑时可以采用代理的技术。

代理分类

静态代理

静态代理是在编译时期就已经确定的代理方式,在静态代理中,需要手动创建一个代理类,该代理类与被代理类实现相同的接口,并持有一个对被代理对象的引用。通过在代理类中调用被代理对象的方法前后加入自定义的逻辑,实现对目标对象方法的增强或控制。

动态代理

动态代理是在运行时期根据被代理对象生成代理类的方式。在动态代理中,不需要手动创建代理类,而是通过使用Java的反射机制,在运行时动态地创建代理类和代理对象。动态代理可以代理任何实现了接口的类,它通过一组接口来描述被代理类的行为,并提供了一个InvocationHandler接口的实现类来处理代理对象的所有方法调用。在方法被调用时,代理对象会将方法的调用转发给InvocationHandler的invoke()方法,并可以在此方法中添加额外的逻辑。

实现方式(动态代理)

两种方法:
  • JDK动态代理:JDK原生的实现方式,需要被代理的目标类必须实现接口!他会根据目标类的接口动态生成一个代理对象!代理对象和目标对象有相同的接口!
  • cglib:通过继承被代理的目标类实现代理,所以不需要目标类实现接口!

AOP 面向切面编程

它允许开发人员分离横切关注点(cross-cutting concerns)和核心业务逻辑。横切关注点是那些存在于应用程序中多个模块中的功能,例如日志记录、性能统计、安全性和事务管理等。通过 AOP,这些横切关注点可以被模块化地定义,并且可以被动态地应用到整个应用程序中。也就是说将核心代码和非核心代码分割开。

使用场景

  1. AOP(面向切面编程)是一种编程范式,它通过将通用的横切关注点(如日志、事务、权限控制等)与业务逻辑分离,使得代码更加清晰、简洁、易于维护。AOP可以应用于各种场景,以下是一些常见的AOP应用场景:
  2. 日志记录:在系统中记录日志是非常重要的,可以使用AOP来实现日志记录的功能,可以在方法执行前、执行后或异常抛出时记录日志。
  3. 事务处理:在数据库操作中使用事务可以保证数据的一致性,可以使用AOP来实现事务处理的功能,可以在方法开始前开启事务,在方法执行完毕后提交或回滚事务。
  4. 安全控制:在系统中包含某些需要安全控制的操作,如登录、修改密码、授权等,可以使用AOP来实现安全控制的功能。可以在方法执行前进行权限判断,如果用户没有权限,则抛出异常或转向到错误页面,以防止未经授权的访问。
  5. 性能监控:在系统运行过程中,有时需要对某些方法的性能进行监控,以找到系统的瓶颈并进行优化。可以使用AOP来实现性能监控的功能,可以在方法执行前记录时间戳,在方法执行完毕后计算方法执行时间并输出到日志中。
  6. 异常处理:系统中可能出现各种异常情况,如空指针异常、数据库连接异常等,可以使用AOP来实现异常处理的功能,在方法执行过程中,如果出现异常,则进行异常处理(如记录日志、发送邮件等)。
  7. 缓存控制:在系统中有些数据可以缓存起来以提高访问速度,可以使用AOP来实现缓存控制的功能,可以在方法执行前查询缓存中是否有数据,如果有则返回,否则执行方法并将方法返回值存入缓存中。
  8. 动态代理:AOP的实现方式之一是通过动态代理,可以代理某个类的所有方法,用于实现各种功能。

Aop名词介绍

  1. 切面(Aspect):横跨多个对象的关注点,如日志记录、安全控制等。切面由切点和通知组成。
  2. 连接点(Join Point):程序执行过程中能够插入切面的点,如方法调用、异常处理等。
  3. 切点(Pointcut):对连接点进行拦截的定义,如拦截某个包下的所有方法调用。
  4. 通知(Advice):切面在连接点处执行的操作,如在方法执行前后添加日志记录、在方法执行发生异常时处理异常等。
  5. 织入(Weaving):将切面应用到目标对象并创建新的代理对象的过程。
  6. 目标对象(Target Object):被切面织入的对象。
  7. 引入(Introduction):在不修改目标对象代码的情况下,为目标对象添加新的方法或属性。
  8. AOP代理(AOP Proxy):AOP框架创建的代理对象,用于实现AOP功能。

SpringAop实现(注解的方式)

接口内容:
package com.ssmLearn;

/**
 *       + - * / 运算的标准接口!
 */
public interface Calculator {
    
    int add(int i, int j);
    
    int sub(int i, int j);
    
    int mul(int i, int j);
    
    int div(int i, int j);
    
}
实现类
package com.ssmLearn;


import org.springframework.stereotype.Component;

/**
 * 实现计算接口,单纯添加 + - * / 实现! 掺杂其他功能!
 */
//最后必须放到ioc
@Component
public class CalculatorPureImpl implements Calculator {
    
    @Override
    public int add(int i, int j) {
        int result = i + j;
        return result;
    }
    
    @Override
    public int sub(int i, int j) {
    
        int result = i - j;
    
        return result;
    }
    
    @Override
    public int mul(int i, int j) {
    
        int result = i * j;
    
        return result;
    }
    
    @Override
    public int div(int i, int j) {
    
        int result = i / j;
    
        return result;
    }
}

需要实现的内容

  1. 在加减乘除方法中加入日志输出
  2. 加入异常方法
实现代码
package com.ssmLearn.Aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

//使用注解配置插入的代理目标
@Aspect
@Component
public class AchiveAop {

    @Before("execution(* com.ssmLearn.CalculatorPureImpl.*(..))")
    public void start(){
        System.out.println("这是初始化方法");
    }
    @After("execution(* com.ssmLearn.CalculatorPureImpl.*(..)))")
    public void end(){
        System.out.println("这是结束方法");
    }

    @AfterThrowing(value = "execution(public int com.ssmLearn.CalculatorPureImpl.*(..))")
    public void catchExection(){
        System.out.println("出现异常");
    }
}
代码编写
  1. 注解 Aspect 指示一个类是一个切面,告诉aop框架在这个位置执行切入
  2. 注解Component用于将这个类放到ioc容器中
  3. 编写具体方法逻辑,填写对应的注解内容 ,将切面表达式写入
配置类
package com.ssmLearn.config;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(basePackages = "com.ssmLearn")
//这个是配置的 aspect代理启动入口
@EnableAspectJAutoProxy
public class javaConfig{
}
代码实现
  1. Configuration标识配置类
  2. ComponentScan扫描包的注解并将它们注册为 Bean。
  3. EnableAspectJAutoProxy这个注解开启了 AspectJ 的自动代理功能。
测试类的书写
import com.ssmLearn.Calculator;
import com.ssmLearn.config.javaConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

//@SpringJUnitConfig(locations = "classpath:spring-aop.xml")
@SpringJUnitConfig(value = {javaConfig.class})
class AopTest {
    @Autowired
    private Calculator calculator;
    @Test
    public void testCalculator(){
        int res = calculator.add(1,0);
        System.out.println("res = " + res);
    }
    @Test
    public void test(){
//        使用配置类 就可以直接使用这个ioc容器 直接使用后AnnotationConfigApplicationContext
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(javaConfig.class);
        Calculator bean = applicationContext.getBean(Calculator.class);
        int res = bean.add(1,2);
        System.out.println("res = " + res);
    }
}
代码实现

实现ioc容器管理需要 创建容器(根据配置类创建)->获取对象(根绝需求获得bean对象)->调用对象的方法(通过指定class文件获取)->关闭容器(避免溢出)

  1. 使用springJunitConfig框架进行测试,填写对应的配置类文件,使用Autowired注解实例化接口。然后使用对象执行相应的方法
  2. 使用AnnotationConfigApplicationContext根绝配置类创建,然后获去对象进行调用

切点表达式

在这里插入图片描述

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

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

相关文章

随记-Java项目处理SQL注入问题

现象:http://10.xx.xx.xx:xx/services/xxService 存在SQL注入情况 加固意见: 需要对网站所有参数中提交的数据进行过滤,禁止输入“"、"xor"、"or"、”--“、”#“、”select“、”and“等特殊字符;所有…

【LongChain-03】在本地运行LLM的另一些案例

​ 一、使用案例说明 PrivateGPT、 llama.cpp和 GPT4All等项目的流行 强调了在本地(在您自己的设备上)运行 LLM 的需求。 这至少有两个重要的好处: Privacy:您的数据不会发送给第三方,并且不受商业服务的服务条款的约…

复旦大学NLP团队发布86页大模型Agent综述

复旦大学自然语言处理团队(FudanNLP)发布了一篇长达86页的综述论文,探讨了基于大型语言模型的智能代理的现状和未来。该论文从AI Agent的历史出发,全面梳理了基于大型语言模型的智能代理现状,包括LLM-based Agent的背景…

Linux系统安全①iptables防火墙

目录 一.iptables防火墙概述 1.netfilter与iptables (1)netfilter (2)iptables 2.iptables防火墙默认规则表、链结构 二.iptables四表五链 1.四表 2.五链 3.总结 三.iptables的配置 1.安装 2.配置方法 (1…

React开发必知必会的Hooks

文章目录 前言1、React的组件创建方式2、什么是Hook?3、Hook总的使用规则 一、useState二、useRef三、useEffect四、useLayoutEffect五、useReducer六、useContext七、memo与useMemo、useCallback1、memo2、useMemo3、useCallback4、三者区别 八、useImperativeHand…

C++重新入门-C++数据类型

目录 1.基本的内置类型 2.typedef 声明 3.枚举类型 4.类型转换 使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。 您可能需要存储…

网站为什么要用CND?

CDN对于网站来说至关重要,CDN对网站的重要性主要体现在可以提升用户体验、提高网站安全性、减轻服务器负担、提高SEO排名等,还可以为网站节省带宽成本。因此,选择一个性能好、速度快的CDN是很有必要的。 CDN对于现代网站来说是不可或缺的&am…

【算法分析与设计】无重复的最长子串

📝个人主页:五敷有你 🔥系列专栏:算法分析与设计 ⛺️稳中求进,晒太阳 题目 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 示例 1: 输入: s "abcabcbb" 输…

redis下载与安装教程(centos下)

文章目录 一,redis下载1.1上传到linux服务器上 二,redis安装2.1 安装依赖2.2 解压包2.3 编译并安装2.4 指定配置启动2.5 设置redis开机自启 一,redis下载 官网: https://redis.io1.1上传到linux服务器上 我用filezila上传到/us…

【前端web入门第四天】02 CSS三大特性+背景图

文章目录: 1. CSS三大特性 1.1继承性 1.2 层叠性 1.3 优先级 1.3.1 优先级1.3.2 优先级-叠加计算规则 2. 背景图 2.1 背景属性2.2 背景图2.3 背景图的平铺方式2.4 背景图位置2.5 背景图缩放2.6 背景图固定2.7 背景复合属性 1. CSS三大特性 1.1继承性 什么是继承性? 子级默…

华大基因PMseq病原微生物高通量基因检测产品耐药数据库持续

23年肺炎支原体感染的患者数量持续上升,与此同时,由肺炎支原体感染引发的住院患者数量也在迅速增加。这就导致近期儿科和发热门诊都处于床位爆满状态。而在疑难危重的肺炎患者中,肺炎支原体的检出率也在不断提高。华大基因PM Online线上数据管…

Python程序设计 函数

简单函数 函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可以实现大量代码的重复使用。 函数的使用包含两个步骤: 定义函数 —— 封装 独立的功能 调用函数 —— 享受 封装 的成果 函数的作用,在开发程序时,使用…

.NET Core Web API使用HttpClient提交文件的二进制流(multipart/form-data内容类型)

需求背景: 在需要通过服务端请求传递文件二进制文件流数据到相关的服务端保存时,如对接第三方接口很多情况下都会提供一个上传文件的接口,但是当你直接通过前端Ajax的方式将文件流上传到对方提供的接口的时候往往都会存在跨域的情况&#xff…

第97讲:MHA高可用集群模拟主库故障以及修复过程

文章目录 1.分析主库故障后哪一个从库会切换为主库2.模拟主库故障观察剩余从库的状态2.1.模拟主库故障2.3.当前主从架构 3.修复故障的主库3.1.修复主库3.2.当前主从架构3.3.恢复MHA 1.分析主库故障后哪一个从库会切换为主库 在模拟MHA高可用集群主库故障之前,我们先…

jenkins 发布远程服务器并部署项目

安装参考另一个文章 配置maven 和 jdk 和 git 注意jdk的安装目录,是jenkins 安装所在服务器的jdk目录 注意maven的目录 是jenkins 安装所在服务器的maven目录 注意git的目录 是jenkins 安装所在服务器的 git 目录 安装 Publish Over SSH 插件 配置远程服务器 创…

C++之函数重载,默认参数,bool类型,inline函数,异常安全

函数重载 在实际开发中,有时候需要实现几个功能类似的函数,只是细节有所不同。如交换两个变量的值,但这两种变量可以有多种类型,short, int, float等。在C语言中,必须要设计出不同名的函数,其原型类似于&am…

DockerUI如何部署结合内网穿透实现公网环境管理本地docker容器

文章目录 前言1. 安装部署DockerUI2. 安装cpolar内网穿透3. 配置DockerUI公网访问地址4. 公网远程访问DockerUI5. 固定DockerUI公网地址 前言 DockerUI是一个docker容器镜像的可视化图形化管理工具。DockerUI可以用来轻松构建、管理和维护docker环境。它是完全开源且免费的。基…

如何部署Linux AMH服务器管理面板并结合内网穿透远程访问

文章目录 1. Linux 安装AMH 面板2. 本地访问AMH 面板3. Linux安装Cpolar4. 配置AMH面板公网地址5. 远程访问AMH面板6. 固定AMH面板公网地址 AMH 是一款基于 Linux 系统的服务器管理面板,它提供了一系列的功能,包括网站管理、FTP 管理、数据库管理、DNS 管…

容器和镜像

容器和镜像是现代软件开发和部署中重要的概念,它们通常与容器化技术(如Docker)相关联。以下是它们的基本定义和关系: 容器(Container): 容器是一种轻量级、可移植的运行环境,其中包含了应用程序及其依赖项(…

leet code141. 环形链表(投机取巧法)只要9行代码!!不看后悔!

今天在力扣上做到这个题 当我看到了10000时我突然想到一种很投机取巧的方法,我们直接链表循环,然后当它循环到10001次的时候我们就直接能说明它是循环链表了! 代码实现(小学生都能看懂) bool hasCycle(struct ListNode *head) { int add…