Spring---AOP(面向切面编程)

news2024/9/24 19:21:03

AOP(Aspect-Oriented Programming: 面向切面编程):将那些与业务无关,却为业务模块所共调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为“切面”(Aspect),便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性;

一、AOP的核心概念

  1. 切面(Aspect)

    • 切面是一个模块,包含了横切关注点的实现。它可以定义在应用程序的多个地方应用的行为。
  2. 连接点(Join Point)

    • 连接点是程序执行的一个点,例如方法调用、对象实例化等。AOP允许在这些连接点上插入切面。
  3. 通知(Advice)

    • 通知是切面在特定连接点执行的动作。根据执行时机的不同,通知可以分为:
      • 前置通知(Before):在连接点之前执行。
      • 后置通知(After):在连接点之后执行。
      • 环绕通知(Around):在连接点前后执行,可以控制连接点的执行。
      • 异常通知(After Throwing):在连接点抛出异常时执行。
      • 最终通知(After Returning):在连接点正常返回时执行。
  4. 切入点(Pointcut)

    • 切入点定义了哪些连接点会被通知所影响。它通常通过表达式来指定。
  5. 织入(Weaving)

    • 织入是将切面与其他应用程序类型或对象结合的过程。织入可以在编译时、类加载时或运行时进行。
  6. AOP目标对象(Target):

    • 就是挖掉功能的方法对应的类生的对象,这种对象是无法直接完成最终工作的

  7. AOC切面:切点+通知

二、AOP的优点

  • 模块化:将横切关注点与业务逻辑分离,提高代码的可读性和可维护性。
  • 重用性:切面可以在多个地方重用,减少代码重复。
  • 灵活性:可以动态地改变应用程序的行为,而不需要修改业务逻辑代码。

三、AOP的实现

在Java中,AOP通常通过框架实现,如Spring AOP和AspectJ。

1.SpringAOP+AspectJ实现步骤

        1.添加依赖,aop与aspectj表达式的依赖

        2.创建spring的主配置文件,bean内的命名空间要添加aop的

        3.创建业务代码并编写日志记录代码(事务管理代码)

        4.将业务层与日志记录层注入spring容器 5.<aop:config>--aop配置 aop:aspect--aop切              面 aop:before--通知内容与通知类型

 Xml

<!--注入业务层-->
业务层 Bean 注入:这行代码将业务层的实现类 AccountServiceImp 注入到 Spring 容器中
    <bean id="accountServiceImp" class="com.xn.service.AccountServiceImp"></bean>


<!--注入日志记录层(通知)-->
日志记录层 Bean 注入:这行代码将日志记录器 Logger 注入到 Spring 容器中。
    <bean id="logger" class="com.xn.util.Logger"></bean>
<!--配置AOP-->
AOP 配置:这部分用于配置 AOP
    <aop:config>



<!--配置切面-->
切面配置:里定义了一个切面,引用了日志记录器 logger。
        <aop:aspect id="aopAspect" ref="logger">

            <!--切点-->切点 dian 定义了所有在 com.xn.service 包下的任意方法的执行。
            <aop:pointcut id="dian" expression="execution(* com.xn.service.*.*(..))"/>


            <!--通知-->这里使用了环绕通知 arroundMethod,它将在切点方法执行前后执行。
<!--        <aop:before method="beforeMethod" pointcut-ref="dian"></aop:before>-->
<!--        <aop:after-returning method="returnMethod" pointcut-ref="dian"></aop:after-returning>-->
<!--        <aop:after-throwing method="throwMethod" pointcut-ref="dian"></aop:after-throwing>-->
<!--        <aop:after method="afterMethod" pointcut-ref="dian"></aop:after>-->
            <aop:around method="arroundMethod" pointcut-ref="dian"></aop:around>
        </aop:aspect>
    </aop:config>

public class Logger {
    public void beforeMethod() {
        System.out.println("日志类logger中调用beforeMethod方法进行日志记录");
    }

    public void returnMethod() {
        System.out.println("日志类logger中调用returnMethod方法进行日志记录");
    }

    public void throwMethod() {
        System.out.println("日志类logger中调用thowMethod方法进行日志记录");
    }

    public void afterMethod() {
        System.out.println("日志类logger中调用afterMethod方法进行日志记录");
    }


    public Object arroundMethod(ProceedingJoinPoint pjp) {

        Object obj = null;
        try {
            System.out.println("环绕通知===前置通知");
            //切点方法
            Object[] ars = pjp.getArgs();
            obj = pjp.proceed(ars);
            System.out.println("环绕通知===返回通知");
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println("环绕通知===异常通知");
        } finally {
            System.out.println("环绕通知===后置通知");
            return obj;
        }


    }
}

注解

<!--扫描注解-->
    <context:component-scan base-package="com.xn"></context:component-scan>
<!--开启spring注解的aop动态代理-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

 

@Component
@Aspect
public class Logger {
    @Pointcut("execution(* com.xn.service.AccountServiceImp.update())")
    public void dian(){

    }
    @Before("dian()")
    public void beforeLogger() {
        System.out.println("前置通知===>日志类logger中调用beforeMethod方法进行日志记录");
    }
    @AfterReturning("dian()")
    public void returnLogger()
    {
        System.out.println("返回通知===>日志类logger中调用returnMethod方法进行日志记录");
    }
    @AfterThrowing("dian()")
    public void throwLogger() {

        System.out.println("异常通知===>日志类logger中调用throwMethod方法进行日志记录");
    }
    @After("dian()")
    public void afterLogger()
    {
        System.out.println("后置通知===>日志类logger中调用afterMethod方法进行日志记录");
    }
    //环绕通知
    @Around("dian()")
    public Object arroundLogger(ProceedingJoinPoint pjp) {

        Object returnobj=null;//保存主业务方法的返回值
        try {
            //前置通知
            System.out.println("环绕通知===前置通知");
            //切点方法
            Object[] objs = pjp.getArgs();//主业务方法的参数
            returnobj = pjp.proceed(objs);//调用主业务方法

            System.out.println("环绕通知===>后置通知");
        } catch (Throwable e) {
            //异常通知
            e.printStackTrace();
            System.out.println("环绕通知===异常通知");
        } finally {
            //最终通知
            System.out.println("环绕通知===最终通知");
            return returnobj;
        }


    }
}

 

 

2.切点表达式配置语法:

execution(修饰符 返回值 包名称.类名称.方法名称(参数列表))
    eg: execution(public void com.apesource.service.ServiceImp.findAll())
    1.修饰符可以省略代表任意
        execution(返回值 包名称.类名称.方法名称(参数列表))
    2.返回值可以使用“*”代表任意
        execution(* 包名称.类名称.方法名称(参数列表))
    3.包名可以使用“*”代表任意名称
        execution(* *.*.*.类名称.方法名称(参数列表))
    4.包名可以使用“..”代表任意个数
        execution(* *...类名称.方法名称(参数列表))
    5.类名与方法名可以使用“*”代表任意
        execution(* *...*.*(参数列表))
    6.参数列表可以使用".."代表任意个数任意类型
        execution(* *...*.*(..))
        如果有参数
            int======>int
            String===>java.lang.String

 

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

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

相关文章

Promethues Metrics

Metrics Metrics可分为三部分&#xff1a; HELP 描述metric作用TYPE metric类别 TYEP Counter 某个事件发生的次数数字只能增长 Total reuqests Total ExceptionsGauge 描述当前值可以上升或下降 CurrentCPU Utilization Available System Memory Number of concurren…

萌新的Java入门日记19

Vue真恶心&#xff01;&#xff01;&#xff01;呜呜呜 5.配置代理 为了避免因后端服务器迁移造成的麻烦&#xff0c;在 vite.config.js 文件中配置如下代码&#xff1a; export default defineConfig({plugins: [vue()],server:{// 配置vite冷启动项目自动使用浏览器访问首页…

【中项】系统集成项目管理工程师-第10章 项目整合管理-10.6实施整体变更控制

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

4个免费好用的免扣素材神器!png素材根本用不完!

你是否曾为找不到合适的PPT素材而头疼&#xff1f;模糊的图片、带水印的模板&#xff0c;还有那些让人抓狂的素材搜索难题。别急&#xff0c;今天就来给大家安利四款我私藏的PPT素材神器&#xff0c;让你的PPT设计从此变得简单又高效&#xff01; 一、千鹿设计助手 — AI免抠图…

算法力扣刷题记录 七十【70. 爬楼梯及算法性能分析:时间复杂度和空间复杂度】

前言 动态规划章节第二篇。记录 七十【70. 爬楼梯】 一、题目阅读 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xf…

SQL注入sqli-labs-master关卡三

第三关如下&#xff1a; 查看该关卡的代码发现其与关卡一和关卡二的不同之处在于id($id)这里。 那么我们输入?id1或?id2)--都能用来判断是字符型还是数字型注入。 接着输入?id1) order by 3--检查它的列数。检查到4报错&#xff0c;说明只有三列。 输入?id-1) union select…

02_快速启动 Demo 创建 Electron 项目、electron-forge 搭建一个 electron 项目、手动创建electron项目

快速启动 Demo 创建 Electron 项目 一、克隆一个仓库、快速启动一个项目二、electron-forge 搭建一个 electron 项目三、手动搭建一个 electron 项目四、开发工具中配置 Eslint 一、克隆一个仓库、快速启动一个项目 要使用 git 的话首先电脑上面需要安装 git //克隆示例项目的…

Cpp中的this指针--复习记录

1.什么是this指针? 每个类都有一个this指针&#xff0c;我们的非静态成员函数可以通过这个this指针来操作对象的成员属性。this指针存储的就是类的实例的地址&#xff0c;this指针时时刻刻指向的都是这个实例对象本身。 由下图可知: 我在主函数中栈上创建了一个类的实例(由操…

数据规模介绍

batch_size 2 1829*2 3658张图片 FSC147数据集介绍 train 3659 val 1286 test 1190

xxl-job 源码梳理(2)-服务端

目录 1. 控制面的接口2.手动触发任务2. 定时任务的实现 1. 控制面的接口 服务端包含xxl-job的管理端&#xff0c;页面上的接口后端一系列的controller接口 appName是一个核心概念&#xff0c;它是指执行器应用的名称&#xff0c;appName是执行器的唯一标识 页面上的接口&#…

出行365:依托分布式数据库,让出行无忧 | OceanBase案例

*本文首发自“新华社环球”杂志&#xff0c;作者张海鑫 每年的暑期旅游旺季&#xff0c;都会触发一轮轮的文旅消费的热潮&#xff0c;对于互联网出行服务行业而言&#xff0c;这既是一场盛大的狂欢&#xff0c;也是对其综合实力的严峻考验。 然而&#xff0c;自去年暑假起&…

Email发送接口安全性保障策略?如何优化?

Email发送接口的高级功能&#xff1f;怎么有效利用邮件API接口&#xff1f; Email发送接口的安全性对于防止数据泄露、滥发垃圾邮件和恶意攻击至关重要。AokSend将探讨Email发送接口的安全性保障策略&#xff0c;帮助开发者和企业确保其电子邮件通信的安全性和可靠性。 Email…

智能猫砂盆买错有什么危害?深度解析三款热门爆款产品!

作为一名家里还有小猫在等待的上班族&#xff0c;我们经常因为需要加班或频繁出差而忙碌得不可开交&#xff0c;导致我们很容易忽略猫咪的厕所环境和健康安全&#xff0c;每次急匆匆地出门&#xff0c;都发现自己似乎忘了给猫咪及时铲屎。但是大家要知道&#xff0c;不及时清理…

为人处世,“会说话”是一生的修行

职场上&#xff0c;常常存在这样一种现象&#xff1a;“会干活的&#xff0c;不如会说的。” 学会“好好说话”、“说正确的话”“说让人舒服的话”成为一生必须要面对的修行。 01 丰厚的学养&#xff0c;是“会说话”的根基。 同一句话&#xff0c;“会说话”的人&#xf…

XXXForm组件

效果展示 代码 XXXForm <template><div class"search-container"><el-form ref"formRef" class"form_is_hidden" :model"form" v-bind"formAttrs"><el-row :gutter"20" class"search…

一文带你快速了解——LVS负载均衡集群

前言&#xff1a; Internet的飞速发展给网络带宽和服务器带来巨大的挑战。从网络技术的发展来看&#xff0c;网络带宽的增长远高于处理器速度和内存访问速度的增长。对用硬件和软件方法实现高可伸缩、高可用网络服务的需求不断增长。针对高可伸缩、高可用网络服务的需求&#x…

.NET8使用VS2022打包Docker镜像

NET8使用VS2022打包Docker镜像 1. 项目中添加Docker支持文件2. 自定义镜像名称3. 发布Docker镜像3.1 安装Docker3.2 控制台切换到项目根目录,执行以下命令发布镜像 3.3 修改镜像名称4. 保存镜像到本地 1. 项目中添加Docker支持文件 2. 自定义镜像名称 项目文件PropertyGroup节…

软件功能测试步骤介绍,软件测试服务公司推荐

在当今软件开发日益复杂的环境中&#xff0c;软件功能测试显得尤为重要。功能测试是确保软件产品满足用户需求和规范要求的关键环节。它通过验证软件功能是否按预期运行&#xff0c;帮助发现潜在的问题&#xff0c;防止软件在上线后导致用户的不满及业务损失。随着市场竞争的加…

(el-Date-Picker)操作(不使用 ts):Element-plus 中 DatePicker 组件的使用及输出想要日期格式需求的解决过程

Ⅰ、Element-plus 提供的DatePicker日期选择器组件与想要目标情况的对比&#xff1a; 1、Element-plus 提供DatePicker组件情况&#xff1a; 其一、Element-ui 自提供的DatePicker代码情况为(示例的代码)&#xff1a; // Element-plus 提供的组件代码: <template><e…

【多线程-从零开始-捌】代码案例2—阻塞队列

什么是阻塞队列 阻塞队里是在普通的队列&#xff08;先进先出队列&#xff09;基础上&#xff0c;做出了扩充 线程安全 标准库中原有的队列 Queue 和其子类&#xff0c;默认都是线程不安全的 具有阻塞特性 如果队列为空&#xff0c;进行出队列操作&#xff0c;此时就会出现阻…