spring boot面向切面编程aop

news2024/11/16 19:05:27

一、什么是AOP

AOP,Aspect Oriented Programming,面向切面编程

举个例子来理解
如果我们的业务需要额外做三件事情,判断是否已经登录,记录日志,统计业务执行时长

传统的做法是这样子的:
在这里插入图片描述
而apo的实现是这样的:
在这里插入图片描述

区别在于:
原本的做法是,需要什么功能,就调用什么功能的方法,需要我们主动去调用

aop的做法是,需要什么功能,就把业务交给相应的代理人,由代理人帮我们去完成,是被动完成的

aop做法的好处是:
1、代码解耦
把不相关的功能都抽取出来,需要使用哪个功能就把业务交给专业的代理人,由代理人去完成。需要新功能的时候,直接添加新的代理业务,这样不会对其它的业务造成影响

2、提高开发效率
当需要使用某个功能时,我们不需要关心代理是怎么做的,只需要简单地使用就好了,就像事务注解@Transactional,只要添加了该注解,方法就会代理,获得了事务的功能,简化了开发

二、AOP的实现示例

Logger 注解:

package com.aop.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Logger {
}

Logger 注解代理类:

package com.aop.aop;

import com.aop.annotation.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * LoggerAop代理类
 */
@Component
@Aspect
public class LoggerAop {

    @Around(value = "@annotation(logger)")
    public Object around(ProceedingJoinPoint pjp, Logger logger) throws Throwable {
        System.out.println("开始记录日志");
        Object proceed = pjp.proceed();
        return proceed;
    }
}

Loggin 注解:

package com.aop.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Login {
    boolean login() default true;
}

Loggin 注解代理类:

package com.aop.aop;

import com.aop.annotation.Login;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;


/**
 * LoginAop代理类
 */
@Component
@Aspect
public class LoginAop {


    @Around("@annotation(login)")
    public Object around(ProceedingJoinPoint pjp, Login login) throws Throwable {
        System.out.println("开始判断登录");
        if(login.login()){
            System.out.println("已经登录,可执行方法");
            Object proceed = pjp.proceed();
            return proceed;
        }else{
            System.out.println("未登录,不执行方法");
            return "请先登录!";
        }
    }
}

Time注解:

package com.aop.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Time {
}

Time注解代理类:

package com.aop.aop;


import com.aop.annotation.Time;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.Date;


/**
 * TimeAop代理类
 */
@Component
@Aspect
public class TimeAop {

    @Around("@annotation(time)")
    public Object around(ProceedingJoinPoint pjp, Time time) throws Throwable {
        long time1 = new Date().getTime();
        Object proceed = pjp.proceed();
        long time2 = new Date().getTime();
        System.out.println("运行了"+((Double.valueOf(time2)-time1)/1000) + "秒");
        return proceed;
    }

}

测试controller类:

package com.aop.controller;


import com.aop.annotation.Logger;
import com.aop.annotation.Login;
import com.aop.annotation.Time;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * RestController,即Controller+ResponseBody,将返回结果转为json字符串响应到客户端
 */
@RestController
public class HelloController {

    /**
     * Logger,打印日志
     * Login,判断登录
     * Time,记录运行时间
     * RequestMapping,请求路径
     *
     */
    @Logger
    @Login
    @Time
    @RequestMapping("/hello")
    public String hello() throws InterruptedException {
        /**
         * sleep,模拟业务时间
         */
        Thread.sleep(500);
        System.out.println("hello");
        return "hello";
    }
}

启动类:

package com.aop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AopApplication {

    public static void main(String[] args) {
        SpringApplication.run(AopApplication.class, args);
    }

}

启动后测试访问:
在这里插入图片描述
在这里插入图片描述
发现方法已经被代理了

如果把注解Login的login属性改为false,则验证没有登录,方法不会执行
在这里插入图片描述

再次访问:
在这里插入图片描述
在这里插入图片描述

三、测试源码

需要自取
链接:https://pan.baidu.com/s/1LcNL7jSYR95GRAnryqFtVg?pwd=uwnq
提取码:uwnq

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

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

相关文章

vue2的数据数据双向绑定

遍历data里面的属性,通过Object.defineProperty的set方法监听属性值的变化,最后通知视图更新 先问自己两个问题: 1.app.message修改数据的时候,Vue内部是如何监听message数据发生改变的 使用Object.defineProperty ->监听对…

概率论的学习和整理17:EXCEL里直接对应的分布公式计算概率(未完成)

1EXCEL计算这些特殊分布的方差 1.1 用原始的概率,期望和方差的方法 虽然计算概率,需要用对应分布的公式P(xn) 想了解的随机变量是总次数n,需要对应几何分布,负二项分布P(xk) 想了解的随机变量是成功次数k,需要对应超几…

算法竞赛,机器学习,深度学习ai学习方向如何规划,搭建环境等答疑

目录 1了解人工智能的背景知识 2 补充数学或编程知识 3 熟悉机器学习工具库 4 系统的学习人工智能 5 动手去做一些AI应用 1了解人工智能的背景知识 本文可以让你避免踩坑走弯路,一些虽然存在但是在研究或者工业上不常用的知识,为自己腾出更多的时间…

Ubuntu软件包安装失败:代码 bionic 和 focal的区别

问题 我在Ubuntu上使用apt安装软件时总是报一些错误,不是版本不对,就是依赖关系不对。尝试了各种方法,突然想到是不是软件源有问题。 查看/etc/apt/sources.list文件,发现使用了阿里云的软件源: deb http://mirrors…

FreeRTOS实时操作系统(十六)内存管理

系列文章 FreeRTOS实时操作系统(一)RTOS的基本概念 FreeRTOS实时操作系统(二)任务创建与任务删除(HAL库) FreeRTOS实时操作系统(三)任务挂起与恢复 FreeRTOS实时操作系统&#x…

Android调用google原生裁剪,兼容三方相册裁剪功能

Android调用google原生裁剪,兼容三方相册裁剪功能 效果图实现功能编写CropImage类继承 ActivityResultContract调用 效果图 实现功能 本篇文章裁剪功能实现兼容Android6,解决部分google手机(有部分Android10的Google手机无法使用google自带裁…

“遇见0和1”小程序正式开源

开源地址 https://gitee.com/lingstudy/meet0and1-applets-share 纯云开发:微信小程序 —“遇见0和1”开源发布 关于小程序 小程序前端使用 ColorUI 组件库,并且参考了大佬“爱敲代码的猫” 的开源项目 WeHalo 的页面设计,后端使用小程序纯云…

stm32读写nand flash

文章目录 1.简介2.频率设置3.FSMC参数设置4.修改宏定义 NAND_DEVICE5.程序测试5.1.简单测试5.2.擦除、写入、读取测试 注意 1.简介 目前我在使用stm32f407ZGT6来读写三星的nand flash【K9F1G08U0E】。 板子我是在这里买的 【STM32F407ZGT6最小系统板/核心板/转接板/开发板/加1…

Python应用实例(二)数据可视化(一)

数据可视化(一) 1.安装Matplotlib2.绘制简单的折线图2.1 修改标签文字和线条粗细2.2 矫正图形2.3 使用内置样式2.4 使用scatter()绘制散点图并设置样式2.5 使用scatter()绘制一系列点2.6 自动计算数据2.7 自定义颜色2.8 使用颜色映射2.9 自动保存图表 数…

QT实现雷达扫描

参考链接&#xff1a;https://www.jb51.net/article/279998.htm 在此基础上做了优化。 效果图&#xff1a; 鼠标左键点击显示当前点相对于圆心的距离和方位 // 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPainter> #include <Q…

Java并发编程(11) —— CountDownLatch原理详解

一、CountDownLatch介绍 在日常开发中经常会遇到需要在主线程中开启多个线程去并行执行任务&#xff0c;并且主线程需要等待所有子线程执行完毕后再进行汇总的场景。在 CountDownLatch 出现之前一般都使用线程的join()方法来实现这一点&#xff0c;但是 join 方法不够灵活&…

jq实现网站-点击标签,添加到一个盒子中,再次点击去掉该标签

实现效果&#xff1a; 代码逻辑&#xff1a; 首先使用hasClass()方法判断点击的标签是否已经存在于盒子中。如果标签已经存在于盒子中&#xff0c;则使用removeClass()方法移除标签的’active’类名&#xff0c;并使用filter()方法找到盒子中与点击的标签文本相同的元素&#…

CAN总线(三)CAN总线链路层的三个标准

1、高速CAN总线 ISO 11898-2中定义了通信速率为125Kbps~1Mbps的高速闭环CAN通信标准,当通信总线长度≤40米,最大通信速率可达到1Mbps,高速闭环CAN(高速CAN)通信如下图所示: 1.1、电气特性 高速CAN总线上为显性电平(逻辑0)时,CAN_H为3.5V、CAN_L为1.5V,此时电压差是…

Qt应用开发——下载安装和HelloWorld

目录 1、下载和安装 2、HelloWorld 1、下载和安装 工欲善其事&#xff0c;必先利其器。第一步环境安装好是必要的过程。Qt 在23年4月份已经更新到了6.5.0&#xff0c;相对于其他的工具&#xff0c;Qt不断在维护升级这一点就非常的友好&#xff0c;这里对版本的迭代更新内容不…

由变上限积分求导到随机变量的概率分布

变上限积分求导书推导 推导过程根据导数的定义和积分的几何意义&#xff0c;看图&#xff1a; 随机变量的概率密度推导 若随机变量x 在 &#xff08;负无穷&#xff0c;正无穷&#xff09;的区间上服从f(x)的概率密度&#xff0c;设y g(x), x h(y)&#xff0c;求y 的概率…

web前端开发工程师的工作职责(合集)

web前端开发工程师的工作职责1 职责&#xff1a; 1.Web前端功能设计、开发和实现&#xff0c;与后台工程师协作&#xff0c;完成数据交互、动态展现; 2.对UI设计的结果进行页面制作(CSS/css3xhtml[表情]ml5JS); 3.熟悉编写可复用的用户接口组件; 4.从视觉和易用性角度&…

Git 安装设置

一&#xff1a;介绍 Git 是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。 二&#xff1a;安装 安装 Git for Windows&#xff0c;网址&#xff1a;https://git-scm.com/ 选择安装组件&#xff1a; 上图红框内的选项是默认勾选的&#xff…

设备集中监控,半导体CMS系统的优势解析

设备集中监控是半导体制造企业中的一项重要任务。传统的设备管理往往存在着分散的监控系统和孤立的报警中心的问题&#xff0c;给企业管理带来了一系列的挑战。而半导体CMS系统的出现&#xff0c;为企业解决了这些问题&#xff0c;并带来了明显的优势。 半导体CMS系统实现了设备…

初识mysql数据库之复合查询

目录 一、多表查询的概念 二、笛卡尔积 1. 笛卡尔积的概念 2. 笛卡尔积使用案例 2.1 显示雇员名、雇员工资以及所在部门的名字 2.2 显示部门号为10的部门名&#xff0c;员工名和工资 2.3 显示所有员工的姓名、工资和工资级别 3. 自连接 3.1 自连接的概念 3.2 自连接案…

idea 中的 pom.xml 文件变为灰色

idea 中的 pom.xml 文件变为灰色被忽略掉了 可能是新建 Module 之前创建了同名 Module&#xff0c; 并进行删除&#xff0c;idea 自动认为该排除此 Module 解决方法&#xff1a; 我们只要到 File → Settings → Build,Execution,Deployment →Ignored Files&#xff0c; …