Aop切面编程(1)

1、aop的使用思想:面向切面的编程,不改变原有代码的基础上,进行拓展,减少代码的冗余,降低耦合性;

2、使用注解进行aop编程,使用自定义注解

2.1导入aop的依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.2新建注解类:TestCut

package com.example.demo.annotations;


import java.lang.annotation.*;

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

    String module() default "测试";

    String descript() default "描述";

}

2.3新建切面类:TestCutAspect

package com.example.demo.aop;

import com.example.demo.annotations.TestCut;
import com.example.demo.common.RestResponse;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;


@Component
@Aspect
public class TestCutAspect {

    @Pointcut("@annotation(com.example.demo.annotations.TestCut)")
    public void testCut(){

    }

    @Before("testCut()")
    public void beforeFun(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            System.out.println(arg.toString());
        }
        //请注意,这种修改是在切面内部进行的,不会影响原始方法中的参数值。
        // 如果你想要修改的是传入原方法的实际参数,而不仅仅是在切面中使用的参数的副本,那么这种方式可能不适用,
        // 因为join point提供的参数是只读的。在这种情况下,你可能需要考虑使用@Around建议来完全控制方法的执行,包括参数的传递。
        args[0]="789";
        System.out.println("注解方式AOP开始拦截, 当前拦截的方法名: " + method.getName());
    }

    @After("testCut()")
    public void afterFun(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        System.out.println("注解方式AOP执行的方法 :" + method.getName() + " 执行完了");
    }


    //1、注意一定要将@Around修饰的方法用Object修饰其返回值,并且返回原方法执行的结果。
    //2、@Around比较万能,尤其是配合ProceedingJoinPoint的使用。使AOP能做的事情更多了。
    //3、@Around如果不执行proceed(),那么原方法将不会执行
    //4、ProceedingJoinPoint 只能在@Around中使用
    @Around("testCut()")
    public Object testCutAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("注解方式AOP拦截开始进入环绕通知.......");
        Object[] args = joinPoint.getArgs();
        //修改args的值,相当于篡改了原方法入参的参数值
        args[0] ="***";
        //获取注解属性
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature =(MethodSignature)signature;
        Method method = methodSignature.getMethod();
        TestCut annotation = method.getAnnotation(TestCut.class);
        String descript = annotation.descript();
        String module = annotation.module();
        System.out.println(module+"|||"+descript);
        //执行原方法
        Object proceed = joinPoint.proceed(args);
        //修改proceed的值,相当于篡改了原方法执行完成之后的返回值
        proceed = RestResponse.error();
        System.out.println("准备退出环绕......");
        return proceed;
    }

    /**
     * returning属性指定连接点方法返回的结果放置在result变量中
     *
     * @param joinPoint 连接点
     * @param result    返回结果
     */
    @AfterReturning(value = "testCut()", returning = "result")
    public void afterReturn(JoinPoint joinPoint, Object result) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        System.out.println("注解方式AOP拦截的方法执行成功, 进入返回通知拦截, 方法名为: " + method.getName() + ", 返回结果为: " + result.toString());
    }

    @AfterThrowing(value = "testCut()", throwing = "e")
    public void afterThrow(JoinPoint joinPoint, Exception e) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        System.out.println("注解方式AOP进入方法异常拦截, 方法名为: " + method.getName() + ", 异常信息为: " + e.getMessage());
    }

}

2.4新建测试类,在需要切面的方法添加注解@TestCut(module = "测试aop",descript = "我是aop的描述属性")

@RestController
@RequestMapping("/aop")
public class AopRestController {

    @RequestMapping("/test")
    @TestCut(module = "测试aop",descript = "我是aop的描述属性")
    public RestResponse test(String aaa,String bbb){
        System.out.println("我是test方法");
        String c = aaa+bbb;
        return RestResponse.successMsg(c);
    }
}

2.5定义统一返回结果

package com.zlkj.file.exception;

import io.swagger.annotations.ApiModelProperty;

/**
 * @author ycy
 */

public class RestResponse {

    @ApiModelProperty(
            name = "success",
            value = "是否成功",
            required = true,
            dataType = "Boolean"
    )
    private Boolean success;

    @ApiModelProperty(
            name = "data",
            value = "返回结果",
            required = false,
            dataType = "Object"
    )
    private Object data;

    @ApiModelProperty(
            name = "msg",
            value = "提示信息",
            required = false,
            dataType = "String"
    )
    private String msg;

    public RestResponse(Boolean success, String msg, Object data){
        this.success = success;
        this.msg = msg;
        this.data = data;
    }

    public static RestResponse success(){
        return new RestResponse(true, null,null);
    }

    public static RestResponse error(){
        return new RestResponse(false, null, null);
    }

    public static RestResponse successMsg(String msg){
        return new RestResponse(true, msg, null);
    }

    public static RestResponse errorMsg(String msg){
        return new RestResponse(false, msg, null);
    }

    public static RestResponse successResult(String msg, Object data){
        return new RestResponse(true, msg, data);
    }

    public static RestResponse errorResult(String msg, Object data){
        return new RestResponse(false, msg, data);
    }

    public Boolean getSuccess() {
        return success;
    }

    public void setSuccess(Boolean success) {
        this.success = success;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "RestResponse{" +
                "success=" + success +
                ", data=" + data +
                ", msg='" + msg + '\'' +
                '}';
    }
}

3、项目结构

4、执行接口

5、通过测试发现常用的aop注解的执行顺序,around包在最外侧;
@around-方法前

@before

@afterReturning

@after

@around-方法后

有异常:

无异常:

通过测试看就是:

1、afterReturning和afterThrow是互斥的二选一;
2、after一定会执行,around后置方法在抛出异常之后不会执行了;

6、around可以修改入参、出参的值;

注意一定要将@Around修饰的方法用Object修饰其返回值,并且返回原方法执行的结果。
 @Around比较万能,尤其是配合ProceedingJoinPoint的使用。使AOP能做的事情更多了。
 @Around如果不执行proceed(),那么原方法将不会执行
 ProceedingJoinPoint 只能在@Around中使用

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人话学Python-基础篇-数字计算

一&#xff1a;数字类型 对于最常见的数据类型,数字在Python中分为三类&#xff1a; 整型(int) 表示的是整数类型的所有数字&#xff0c;包括正整数&#xff0c;负整数和0。和C语言不同的是&#xff0c;Python中的int型没有范围的限制&#xff0c;理论上可以从无限小的整数取到…

文献阅读:基于测序的空间转录组方法的系统比较

文献介绍 文献题目&#xff1a; Systematic comparison of sequencing-based spatial transcriptomic methods 研究团队&#xff1a; 田鲁亦&#xff08;广州实验室&#xff09;、刘晓东&#xff08;西湖大学&#xff09; 发表时间&#xff1a; 2024-07-04 发表期刊&#xff…

【YOLO格式的数据标签,目标检测】

标签为 YOLO 格式&#xff0c;每幅图像一个 *.txt 文件&#xff08;如果图像中没有对象&#xff0c;则不需要 *.txt 文件&#xff09;。*.txt 文件规格如下: 每个对象一行 每一行都是 class x_center y_center width height 格式。 边框坐标必须是 归一化的 xywh 格式&#x…

上传图片,base64改为文件流,并转给后端

需求&#xff1a; html代码&#xff1a; <el-dialog v-model"dialogPicVisible" title"新增图片" width"500"><el-form :model"picForm"><el-form-item label"图片名称&#xff1a;" :label-width"10…

开放式耳机哪个品牌比较好?2024最值得推荐的火爆机型!!

在这个快节奏的时代&#xff0c;我们都在寻找那些既能让我们享受音乐&#xff0c;又能保持对外界感知的音频设备。开放式耳机以其独特的设计&#xff0c;满足了这一需求&#xff0c;它们让你在享受音乐的同时&#xff0c;还能听到周围环境的声音&#xff0c;无论是安全出行还是…

【机器学习】作业 Exam1

线性回归预测 唉&#xff0c;研0了&#xff0c;得学机器学习了。当然还是听的吴恩达老师的课&#xff0c;虽然全是英文&#xff0c;但是&#xff0c;怎么评价呢&#xff0c;讲得既专业又通俗易懂&#xff0c;初学者(像我这样的菜鸡)都值得一看&#xff01;&#xff01; 根据人…

更深入了解汽车与航空电子等安全关键型应用的IP核考量因素

作者&#xff1a;Philipp Jacobsohn&#xff0c;SmartDV高级应用工程师 中国已经连续十多年成为全球第一大汽车产销国&#xff0c;智能化也成为了汽车行业发展的一个重要方向&#xff0c;同时越来越多的制造商正在考虑进入无人机和飞行汽车等低空设备&#xff0c;而所有的这些…

以太网电路相关功能说明

RJ45模块用于PHY芯片之间的互连&#xff0c;如图1所示&#xff0c;RJ45有两种组合形式&#xff0c;一种是分立式&#xff0c;网口变压器和RJ45连接座是分开的&#xff0c;另一种是网口变压器和RJ45集成在一起。 图1 RJ45两种主要形式 接下来以分立式RJ45的百兆网电路做个说明&a…

Xilinx FPGA UltraScale SelectIO 接口逻辑资源

目录 1. 简介 2. Bank Overview 2.1 Diagram 2.2 IOB 2.3 Slice 2.4 Byte Group 2.5 I/O bank 示例 2.6 Pin Definition 2.7 数字控制阻抗(DCI) 2.8 SelectIO 管脚供电电压 2.8.1 VCCO 2.8.2 VREF 2.8.3 VCCAUX 2.8.4 VCCAUX_IO 2.8.5 VCCINT_IO 3. 总结 1. 简介…

Intewell+Codesys高实时运控解决方案

IntewellCodesys高实时运控解决方案 IntewellCodesys方案&#xff0c;基于X86、ARM、MIPS、RISC-V等不同架构的硬件平台&#xff0c;通过Intewell实时操作系统的多种构型形态&#xff0c;包括Intewell-RTOS&#xff0c;Intewell-Win&#xff0c;Intewell-Lin&#xff0c;Intewe…

详解TCP和UDP通信协议

目录 OSI的七层模型的主要功能 tcp是什么 TCP三次握手 为什么需要三次握手&#xff0c;两次握手不行吗 TCP四次挥手 挥手会什么需要四次 什么是TCP粘包问题&#xff1f;发生的原因 原因 解决方案 UDP是什么 TCP和UDP的区别 网络层常见协议 利用socket进行tcp传输代…

查看oracle ojdbc所支持的JDBC驱动版本

oracle jcbc驱动的下载地址参考&#xff1a;JDBC and UCP Downloads page 其实上文中对ojdbc所支持的JDBC驱动版本已经有说明了&#xff0c;不过&#xff0c;因为oracle的驱动包很多时间&#xff0c;都是在公司内部私服里上传维护的&#xff0c;上传的时候&#xff0c;可能又没…

鲸发卡系统 /pay/xinhui/request_post 任意文件读取漏洞复现

0x01 产品简介 鲸发卡系统 致力于解决虚拟商品的快捷发卡服务&#xff0c;为商户及其买家 提供&#xff0c;便捷、绿色、安全、快速的销售和购买体验。框架已升级TP最新版本&#xff0c;无安全BUG&#xff0c;重新开发将近80&#xff05;&#xff0c;原创功能10项&#xff0c;…

static-02

三个注意点 1.静态方法中无this关键字 2.静态方法只能访问静态资源 3.非静态方法可以访问所有 1.静态方法中无this关键字--------(非静态)普通方法里有this关键字(隐藏的) this关键字:代表方法调用者的地址值----这个方法的调用者的就是一个具体的对象 非静态的东西通常跟…

使用virt-manager添加宿主机上的U盘

1、打开virt-manager管理界面 [rootkvm4 ~]# virt-manager 2、打开需要添加U盘的虚拟机 3、进入Hardware管理器 4、选择插入U盘的设备&#xff0c;点Finish 5、进入虚拟机&#xff0c;确认U是否添加OK

基层医院、专科医院云HIS系统,支持电子病历四级,全套源码交付

云HIS系统采用B/S架构云端SaaS服务的方式提供&#xff0c;使用用户通过浏览器即能访问&#xff0c;无需关注系统的部署、维护、升级等问题&#xff0c;系统充分考虑了模板化、配置化、智能化、扩展化等设计方法&#xff0c;覆盖了基层医院的主要工作流程&#xff0c;能够与监管…

倩女幽魂游戏攻略:装备攻略大全与云手机助力教程!

在《倩女幽魂》这片古风奇幻的江湖中&#xff0c;装备不仅是角色的外在装扮&#xff0c;更是提升实力、闯荡三界的关键所在。本文将从装备的颜色、类别、词缀及获取途径等多个维度&#xff0c;为玩家呈现一份详尽而深入的装备攻略&#xff0c;助你成为三界中的佼佼者。 在倩女幽…

PDM系统中物料分类与编码规则生成方案

在企业管理软件中&#xff0c;PDM系统是企业管理的前端软件&#xff0c;用于管理研发图纸、BOM等数据&#xff0c;然后生成相关物料表或BOM&#xff0c;递交给后端ERP系统进行生产管理。在PDM系统中&#xff0c;有两种方式可以生成物料编码。 1第一种是用户可以通过软件接口将…

windows10下的游戏怎么卸载?

在Windows 10中卸载游戏可以通过多种途径进行&#xff0c;下面是一些常见的方法&#xff1a; 方法一&#xff1a;通过“设置”应用卸载 1. 点击左下角的“开始”按钮&#xff0c;打开“开始”菜单。 2. 选择“设置”图标&#xff08;齿轮形状&#xff09;。 3. 在“设置”窗…

【系统架构设计】计算机组成与体系结构(一)

计算机组成与体系结构 计算机系统组成计算机硬件组成控制器运算器主存储器辅助存储器输入设备输出设备 计算机系统结构的分类存储程序的概念Flynn分类 复杂指令集系统与精简指令集系统总线 存储器系统流水线 兜兜转转&#xff0c;最后还是回到了4大件&#xff0c;补基础&#x…