Spring AOP续--织入

news2024/11/16 5:34:04

上篇讲到SpringAOP的一些用法以及概念,这里我们单独讲一下AOP中的“织入”。
我们知道,SpringAOP是基于动态代理实现的技术,而织入则是一个生成动态代理对象并且将切面和目标对象方法编织成为约定流程的过程。

对于通知,上篇文章中都是采用接口+实现类的方式,这也是Spring推荐的方式,但并不是强制的,动态代理的实现方式也是有很多种的,目前主流的就是JDK、CGLIB、Javassist、ASM等。对于Spring来说,它采用了JDK、CGLIB动态代理方式。

首先我们来看看JDK、CGLIB动态代理的区别。

JDK、CGLIB动态代理的区别

JDK动态代理

JDK代理使用的是反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
JDK创建代理对象效率较高,执行效率较低;
JDK动态代理机制是委托机制,只能对实现接口的类生成代理,通过反射动态实现接口类;
JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,需要满足以下要求:
 1.实现InvocationHandler接口,重写invoke()
 2.使用Proxy.newProxyInstance()产生代理对象
 3.被代理的对象必须要实现接口

CGLIB动态代理

CGLIB代理使用字节码处理框架asm,对代理对象类的class文件加载进来,通过修改字节码生成子类。
CGLIB创建代理对象效率较低,执行效率高。
CGLIB则使用的继承机制,针对类实现代理,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,因为是继承机制,不能代理final修饰的类。
CGLib 必须依赖于CGLib的类库,需要满足以下要求:
 1.实现MethodInterceptor接口,重写intercept()
 2.使用Enhancer对象.create()产生代理对象

参考:https://blog.csdn.net/qq_59527118/article/details/127386305

Spring Boot动态代理验证

Spring Boot会自己判断使用哪种代理,如果被代理类有接口,就采用JDK动态代理,否则就采用CGLIB动态代理。
然而,在Spring Boot2.X版本中,Spring Boot不管被代理类是否有实现接口,都会默认采用CGLIB动态代理,如果要让其使用JDK动态代理,则需要在application.properties文件中添加以下配置:

spring.aop.proxy-target-class=false

下面让我们一起验证以下。
首先我们创建两个service类,一个实现了接口,一个没有实现接口,代码如下:

@Service
@Slf4j
public class UserServiceImpl implements IUserService{

    @Override
    public void printUser(User user) {
        if(null == user){
            throw new IllegalArgumentException();
        }
        log.info("用户信息如下:{}", user.toString());
    }
}


@Service
@Slf4j
public class UserServiceNoImpl{

    public void printUser(User user) {
        if(null == user){
            throw new IllegalArgumentException();
        }
        log.info("用户信息如下:{}", user.toString());
    }
}

然后将这两个类的printUser都创建切点以及通知,再创建测试controller:

@RestController
@Slf4j
public class UserController {
    @Autowired
    private IUserService userService;

    @Autowired
    private UserServiceNoImpl userServiceNo;

    @GetMapping("/getUser")
    public User getUser(){
        User user = new User()
                .setId(111)
                .setName("admin")
                .setNote("aop测试")
                ;
        // 实现了接口
        userService.printUser(user); // 断点处
        // 没有实现接口
        userServiceNo.printUser(user);
        try {
            userService.printUser(null);
        }catch (Exception e){
            log.warn("获取用户信息异常:");
        }
        return user;
    }

此时application.properties文件中不添加“spring.aop.proxy-target-class=false”,最后启动应用,访问地址,结果如下:
在这里插入图片描述
可以看到,此时UserServiceImpl 类有实现接口,但是Spring Boot仍然使用了CGLIB代理。

下面让我们在application.properties文件中添加“spring.aop.proxy-target-class=false”,再次启动应用,访问地址,结果如下:
在这里插入图片描述
可以看到,UserServiceImpl 类有实现接口,Spring Boot使用了JDK代理。

好了,今天就先到这里了,眼过千遍不如手过一遍,赶紧去自己尝试一下吧。。。。拜拜

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

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

相关文章

数字化转型导师坚鹏:如何制定与实施企业数字化转型年度培训规划

如何制定与实施企业数字化转型年度培训规划 ——以推动企业数字化转型战略落地为核心,实现知行果合一 课程背景: 很多企业都在开展企业数字化转型培训工作,目前存在以下问题急需解决: 缺少针对性的企业数字化转型年度培训规划…

Python每日一练(20230507) 丑数I\II\III、超级丑数

目录 1. 丑数 Ugly Number I 2. 丑数 Ugly Number II 3. 丑数 Ugly Number III 4. 超级丑数 Super Ugly Number 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 丑数 Ugly Number I …

JavaWeb——1.JavaWeb概述

这是我们javaweb的第一篇文章,首先我们来介绍一下什么是Javaweb JavaWeb:使用java语言完成服务器端程序开发 如下面这张图所示: 可能不太好理解,那么就用通俗的语言来解释一下。 任何的一个应用程序,首先它会有页面…

在 Python 中将秒转换为小时、分钟和秒

文章目录 在 Python 中使用数学计算将秒转换为小时、分钟和秒的自定义函数在 Python 中使用 divmod() 函数将秒转换为小时、分钟和秒在 Python 中使用 DateTime 模块将秒转换为小时、分钟和秒在 Python 中使用时间模块将秒转换为小时、分钟和秒 本篇文章将讨论使用 Python 中的…

Golang每日一练(leetDay0058) 比较版本号、分数转小数

目录 165. 比较版本号 Compare Version Numbers 🌟🌟 166. 分数到小数 Fraction To Recurring Decimal 🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 …

Python动态绘图详解

文章目录 示例FuncAnimation三维情况 示例 matplotlib中的animation提供了动态绘图功能,下面列举一个最简单的动态绘制三角函数的例子,来初步演示一下。 import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animatio…

深入理解Java虚拟机——垃圾收集器

1.前言 在前面我们已经说过了垃圾收集算法,那么现在我们要讲的垃圾收集器,实际上就是对垃圾收集算法的实践。 首先我们先看一张图,这张图可以帮助我们了解各款经典垃圾收集器之间的关系: 图中的垃圾收集器所在的区域代表了它是属…

学系统集成项目管理工程师(中项)系列18b_进度管理(下)

1. 制定进度计划 1.1. 分析活动顺序、持续时间、资源需求和进度制约因素,创建项目进度模型的过程 1.2. 输入 1.2.1. 进度管理计划 1.2.2. 活动清单 1.2.3. 活动属性 1.2.4. 项目进度网络图 1.2.5. 活动资源需求 1.2.6. 资源日历 1.2.7. 活动持续时间估算 …

Linux网络编程——套接字网络编程预备知识

0.关注博主有更多知识 操作系统入门知识合集 目录 1.理解IP地址和MAC地址 2.认识端口号 3.感性认识TCP协议和UDP协议 4.网络字节序 5.socket编程接口 1.理解IP地址和MAC地址 事实上在上一篇博客当中粗浅了介绍一个IP地址MAC地址,其中我们知道IP地址提供方向…

坐标系变换推导(欧拉角、方向余弦矩阵、四元数)+代码解析

一、为什么选择四元数 描述两个坐标系之间的变换关系主要有几个方法 1、欧拉角法(存在奇异性和万向锁而且三个轴旋转的顺序不好定) 2、方向余弦矩阵法(翻译为Directional cosine matrix,简称DCM,也称为旋转矩阵,看了很多博客写的是C11-C33的那…

【Python实操】如何快速写一个乒乓球游戏?

文章目录 前言一、 导入 turtle 和 Screen二、创建一个球3.创建一个 AI 挡板4.创建自己的挡板5.创建移动AI挡板的函数6.创建一个函数以移动你的挡板并用键盘控制它7.全部代码总结 前言 本文提供了一个 Python 实现的乒乓球游戏代码,你只需要将代码复制并粘贴到编辑…

如何防御流量攻击

随着互联网的发展,网络安全问题也日益突出。其中,流量攻击成为网络攻击的一种常见手段。那么流量攻击属于什么攻击,服务器防御流量攻击的方法有哪些呢?本文小编将为您一一解答。 一、流量攻击是什么? 流量攻击即DDoS攻击,全称为…

如何进行DNS优化

在互联网时代,网站的访问速度直接影响着用户体验和转化率。而DNS(Domain Name System)作为域名解析系统,负责将域名转换为IP地址,是网站访问速度的重要因素之一。因此,DNS优化成为了提升网站速度的重要手段之一。 DNS优化到底是什…

SpringMVC-RESTful

REST风格 1. REST简介1.1 REST介绍1.2 RESTful介绍1.3 注意事项 2. RESTful入门案例2.1 快速入门2.2 PathVariable介绍2.3 RequestBody、RequestParam、PathVariable区别和应用 3. REST快速开发【重点】3.1 代码中的问题3.2 Rest快速开发 4. 案例:基于RESTful页面数…

拿捏c语言循环

📕博主介绍:目前大一正在学习c语言,数据结构,计算机网络。 c语言学习,是为了更好的学习其他的编程语言,C语言是母体语言,是人机交互接近底层的桥梁。 本章用循环去写一些题目。 让我们开启c语言…

Kubernetes系列---Kubernetes 理论知识 | 初识

Kubernetes系列---Kubernetes 理论知识 | 初识 1.K8s 是什么?2.K8s 特性3.小拓展(业务升级)4.K8s 集群架构与组件①架构拓扑图:②Master 组件③Node 组件 五 K8s 核心概念六 官方提供的三种部署方式 1.K8s 是什么? K…

springboot打包成jar包运行到服务器 java v 1.8

1.项目打包成jar包 1.1 1.2 2 jdk安装 2.1 jdk 官网 -> oracle 官方的jdk https://www.oracle.com/java/technologies/downloads/#java8 2.2 本地上传文件到服务器 2.3 配置安装 tar -zvxf jdk-8u131-linux-x64.tar.gz -->解压修改配置文件 source /etc/profile /…

Java 10 字符串

1.API 1.1API 概述 什么是API ​ API (Application Programming Interface) :应用程序编程接口 java 中的 API ​ 指的就是 JDK 中提供的各种功能的 Java 类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只…

C++好难(3):类和对象(中篇)

【本章目标】 类的6个默认成员函数构造函数析构函数拷贝构造函数赋值运算符重载const成员函数取地址及const取地址操作符重载 目录 【本章目标】 1.类的6个默认成员函数 2.构造函数 2.1概念 2.2构造函数的特性 特性一 特性二 特性三 特性四 特性五 特性六 特性七 …

Monkey Patching in Go

gomonkey 用来给函数打桩,这种使用一个新的方法实现来替换原来的实现逻辑,怎么看都觉得很神奇。举个例子,在单测中方法 json.Marshal 可以被 gomonkey 覆写成另一种逻辑实现,我准备从原理和使用的角度来看看 gomonkey。主要是来看…