关于对Spring的理解,以及对spring中的两大核心概念AOP和IOC的理解

我们先来说一说Spring,从总体上Spring就是一个基础框架,同时Spring给我们提供了一个Bean容器,用来装载和管理具体的Bean对象,你像我们之前创建对象的时候就是通过new关键字来实现的,但是现在我们只需要告诉容器有哪些对象,就会帮我们去创建好并且管理他的生命周期;然后呢,Spring又是Spring Boot,Spring Cloud等框架的基石,在原有Spring上去做了一些扩展和开发的;

Bean生命周期:

  • 定义Bean:通过<Bean>标签或者(@Bean,@Component)注解来进行定义Bean,这一步Spring并不会去创建Bean,只是将Bean的描述信息存储起来,等待后续的实例化和初始化

  • 注册Bean:将定义信息会注册到BeanFactoey或者ApplicationContext中

  • 实例化Bean(createBeanInstance):根据注解和配置文件实例化Bean,在实例化之前有一个方法postProcessMergedBeanDefinition()对Bean进行一些额外的配置或者修改,主要是对元数据进行一些修改

  • DI属性注入:Spring将类通过构造器,setter方法或者接口注入到Bean实例当中

    其中过程中可能会插入一些自定义的逻辑(postProcessAfterInstantiation)和(postProcessProperties)一些Bean属性的修改和校验操作

    • 初始化之前调用一些Aware接口,在初始化之前去获取Bean的名称、Beanfactory、ApplicationContext方法中的一些前置操作,比如代理包装和AOP切面等

  • 初始化Bean(initializeBean):调用initializeBean的afterPropertiesSet()方法或者通过init-method属性指定的初始化方法

    • 初始化之后,通过一些BeanPostProcessor后置处理器进行一些处理(勾子和后置处理器)

  • 调用Bean:初始化完成,就可以被容器中的Bean使用

  • 销毁Bean:容器关闭时,Spring有三种销毁方法:通过@preDestory方法;实现DisposableBean接口的destory()方法;或者可以自定义销毁方法

DI:依赖注入

然后又可以提出两个核心概念IOC和AOP:

  • IOC(控制反转):是一种控制反转的思想,通过依赖注入实现的。IOC让对象的创建和管理都交给容器来实现,而不是对象本身

    • 核心思想控制其实就是控制对象的创建,ICO容器通过配置文件来创建对象,在对象的生命周期中,在不同时期通过不同配置来进行对象的创建和改造;反转其实就是关于我们创建对象和注入依赖的过程,本来是由我们程序员在代码中指定的,而反转之后,这个动作就交给ICO容器触发,由主动获取变成被动得到,在创建对象A的时候,发现依赖对象B,IOC容器就会根据配置文件,创建B,将B注入A中

    • 依赖注入:通过构造器注入、setter注入或者接口注入,将对象所需要的依赖传递给它,而不是让对象自行创建依赖

    • 优点:1.降低耦合度:减少代码之间的直接依赖,代码更容易维护和扩展。 2.提高可测试性:更容易替换依赖进行单元测试,测试更方便。 3.增强灵活性:依赖关系可以通过配置文件或注解更改,代码更灵活。 4.促进接口编程:有助于编写更灵活的代码,遵循面向接口编程的原则。 5.简化管理:容器管理对象的创建和生命周期,开发更高效。 6.组件重用:组件可以更方便地组合使用,减少重复代码。

  • AOP(面向切面编程):是一种编程范式,通过横切关注点将与业务逻辑无关的分离出来,允许开发者通过“切面”将通用功能模块化,将其应用到程序中的多个地方,避免代码重复。(例如日志记录,控制权限,安全检查,事务管理等)

    • 核心思想:将与业务逻辑无关的横切关注点抽取出来,通过动态代理的方式应用到业务方法,而不是将代码直接写入业务逻辑

    • 基本概念

      • 切面:横切关注点的模块化,比如日志、事务等。可以包含多个通知;

      • 连接点:程序执行中的某个点或者位置,例如方法调用,异常处理、字段访问等;

      • 通知:定义在连接点处执行的动作,可以是一些方法前后,方法抛出异常时的操作

      • 切入点:定义在哪些连接点处的应用通知

    • 动态代理

      • JDK动态代理:通过代理接口来创建一个代理对象,代理对象实现目标类所实现的接口。依赖Java反射机制,由Proxy类和InvocationHandler接口来实现,代理类在运行时,调用其中的invoke()方法

        • 优点:简单高效,代理类是接口的实现类,不需要第三方库,Java自带支持

        • 缺点:只能为实现了接口的类生成代理,如果目标没事实现接口,就无法使用JDK动态代理

        • public class test1 {public static void main(String[] args) {Car car = new CarImpl();//生成代理对象,在调用方法时会转发到invoke方法Car proxy = (Car) Proxy.newProxyInstance(car.getClass().getClassLoader(),car.getClass().getInterfaces(),new CarInvocationHandler(car));//这里drive方法会触发invoke方法proxy.drive();}
          }
          interface Car {void drive();
          }
          class CarImpl implements Car {@Overridepublic void drive() {System.out.println("Car is driving...");}
          }class CarInvocationHandler implements InvocationHandler {//在创建对象的时候,接受一个target代理目标对象private Object target;public CarInvocationHandler(Object target) {this.target = target;}//invoke方法时InvocationHander接口中必须实现的方法,所有通过代理对象调用的方法都会进入这里@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method " + method.getName());Object result = method.invoke(target, args);System.out.println("After method " + method.getName());return result;}
          }
      • CGLIB动态代理:通过生成目标类的子类,并重写目标类中的方法来实现代理,代理类会覆盖目标类中的方法,并在调用方法前后进行逻辑加强

      • 优点:能够处理没有实现接口的类,这是相比较JDK动态代理的优势,可以适用于所有类

      • 缺点:生成目标子类,如果在大量创建代理对象的话,开销可能会很大,性能可能也会比较低,不能代理final类或者final方法,因为final不能被继承

      • class Car {public void drive() {System.out.println("Car is driving...");}
        }class CarInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method " + method.getName());Object result = proxy.invokeSuper(obj, args); // 调用父类方法System.out.println("After method " + method.getName());return result;}
        }public class test2 {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(Car.class);enhancer.setCallback(new CarInterceptor());Car carProxy = (Car) enhancer.create();carProxy.drive();}
        }

         

  • **循环依赖问题**:就是指两个或者多个模块,类,组件之间相互依赖,相乘闭环;简单举一个例子,当A实例化完成以后,要去进行DI属性注入,去getBean(B),但是B还没有创建,那我就转去实例化B,同样,在B中DI属性注入的时候也拿不到A,导致了循环依赖的发生;

    - **解决方法**(自定):一个简单的解决方案,在Bean对象实例化完成后,就放入到一个缓存容器中,当其他Bean对象需要获取到他时可以去缓存中调用,利用缓存去提前暴露对象

    - **解决方法**:其实无论用什么方法关键都是得提前暴露未创建完毕的Bean

      ​    在Spring中主要使用三级缓存来解决缓存依赖:

      - 一级缓存:用于存储完全初始化完成的单例Bean
    - 二级缓存:存储没有完全初始换,但是已经实例化的Bean,用于提前暴露对象,避免出现循环依赖问题
    - 三级缓存:储存对象工厂,当需要时,可以通过工厂创建早期的Bean

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

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

相关文章

Next Terminal 实战:内网无密码安全登录

本文首发于 Anyeの小站&#xff0c;点击阅读原文体验更加。 前言 在日常的 HomeLab 或小型私有云环境中&#xff0c;我们常常通过反向代理&#xff08;如 Nginx、Caddy 等&#xff09;将内网服务暴露到公网&#xff0c;方便远程访问。然而&#xff0c;一旦端口映射开启、公网…

WebSocket断线重连机制:保障实时通信的高可用性

一、为什么需要断线重连&#xff1f;WebSocket虽提供全双工通信能力&#xff0c;但实际环境中连接稳定性受多重威胁&#xff1a;​​网络层波动​​&#xff1a;Wi-Fi切换、4G/5G信号抖动&#xff08;触发onclose事件&#xff09;​​服务端异常​​&#xff1a;服务器宕机、主…

低空三维多物理场耦合风洞试验,保证飞行器的性能安全是低空飞行的底线,是低空经济发展的基础

风墙\风矩阵开发背景&#xff1a;2024年被称为中国低空经济产业发展元年&#xff0c;国家发改委提出“无安全、不低空”原则&#xff0c;要求低空经济产业在技术研发、适航认证、运营管理各环节优先保障安全。目前无人机及其他低空飞行器技术已深度融入军事、民用与工业领域&am…

中文基于Qwen3-235B-2507蒸馏数据集的操作

中文基于Qwen3-235B-2507蒸馏数据集的操作 flyfish 方式1 from datasets import load_dataset from transformers import AutoTokenizer# -------------------------- 配置参数 -------------------------- TOKENIZER_PATH "/media/models/models/Qwen/Qwen3-8B/" #…

论文阅读笔记:《Dataset Distillation by Matching Training Trajectories》

论文阅读笔记&#xff1a;《Dataset Distillation by Matching Training Trajectories》1.动机与背景2.核心方法&#xff1a;轨迹匹配&#xff08;Trajectory Matching&#xff09;3.实验与效果4.个人思考与启发主体代码算法逻辑总结一句话总结&#xff1a; 这篇论文通过让合成…

STM32标准库的工程创建

一.所需文件说明 1.启动文件startup_xxxx.s 作用&#xff1a;初始化堆栈指针、复位向量、中断向量表&#xff0c;执行 SystemInit() 后跳转到 main()。 位置&#xff1a;Libraries/CMSIS/Device/ST/STM32Fxx/Source/Templates/arm/ 文件名&#xff1a; startup_stm32f10x_l…

k8s ceph sc 设置文件系统格式化参数

前言 默认的 sc 文件系统 inode 太少,对于小文件场景,往往会出现容量没满,inode 已经用尽的情况,本文说明如何设置 inode。 说明 本文使用的是 rook-ceph 部署的 ceph 作为存储后端。 xfs 文件系统 sc 创建带格式化参数的 xfs 文件系统的 sc allowVolumeExpansion: t…

关于Npm和Nvm的用法

npm是个什么东西 npm是什么 node package managernodejs包管理工具处理复杂的包的管理的问题那么使用npm以后就不需要从前端引入相应的代码和文件等。 npm相关的命令 查看版本npm -v 更新npm install npm5.4.0 更新到最新版本npm install npmlatest 初始化项目 npm ini…

MyBatis高效查询:简化JDBC开发实战

Mybatis MyBatis 是一款优秀持久层(DAO)框架&#xff0c;用于简化 JDBC 开发 &#xff0c;原是 Apache 开源项目 iBatis&#xff0c;经历迁移改名&#xff0c;2010 年从 Apache 迁到 Google Code 并改名&#xff0c;2013 年 11 月迁至 GitHub&#xff0c;官网为 https://mybati…

系统信息及进程管理命令

系统信息及进程管理 一、系统信息查看 常用命令&#xff1a;uname、hostnam、hostnamectl、uptime、df、du、free、lscpu 1、uname (1)、命令简介 uname 是一个在 Unix 和类 Unix 系统&#xff08;如 Linux、macOS&#xff09;中常用的命令行工具&#xff0c;用于显示系统信息。…

【Z字形变换】

代码思路分析&#xff1a;Z 字形变换 1. 边界情况处理 if (r 1 || r > n) return s;r 1&#xff1a;只有一行&#xff0c;直接返回原字符串&#xff08;无需变换&#xff09;。r > n&#xff1a;行数大于等于字符串长度&#xff0c;每行只有一个字符&#xff0c;直接返…

VBA中类的解读及应用第二十五讲:把源数据赋给类利用类完成查找

《VBA中类的解读及应用》教程【10165646】是我推出的第五套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。类&#xff0c;是非常抽象的&#xff0c;更具研究的价值。随着我们学习、应用VBA的深入&#xff0c;…

Vue3核心语法进阶(Hook)

Vue3 自定义 Hook&#xff1a;让你的代码像乐高一样“可复用”&#xff01;大家好&#xff0c;我是你们的前端小伙伴&#xff01;上一篇我们聊了 Vue3 的生命周期&#xff0c;今天咱们继续深入 Vue3 的核心利器——自定义 Hook&#xff08;Custom Hook&#xff09;。如果你已经…

工控领域协议之Modbus

Modbus 是一种通信协议&#xff0c;用于工业自动化领域中的设备之间的通信。它是一种串行通信协议&#xff0c;广泛应用于连接不同设备、传感器和执行器的工业控制系统。 Modbus 在工业控制系统、自动化设备、能源管理系统等领域得到广泛应用。 Modbus 协议的基本特点&#xff…

大件垃圾识别 mAP↑28%:陌讯多模态融合算法实战解析

一、行业痛点&#xff1a;大件垃圾识别的现实困境在城市环卫智能化转型过程中&#xff0c;大件垃圾&#xff08;如废旧家具、电器等&#xff09;的自动化识别与分拣成为关键环节。据住建部《城市环境卫生发展报告》显示&#xff0c;传统人工分拣模式下大件垃圾识别准确率不足 6…

vk框架或者普通函数封装的一些函数可以拿取使用【会持续更新】

1.身份证校验【通用】/*** function isIDCard* description 判断是否为有效的身份证号码。* param {string} idCard - 待验证的身份证号码。* returns {boolean} 返回验证结果。*/ pubFun.isIDCard function (idCard) {// 身份证号码为15位或者18位&#xff0c;15位时全为数字…

如何给Word和WPS文档添加密码或取消密码

要保护Word和WPS文档&#xff0c;可以为它们加密&#xff0c;加密有两类&#xff1a;打开密码和修改密码。密码设置有两个入口&#xff0c;一个是在另存为&#xff0c;一个是在文件菜单。Word和WPS文字的路径略有不同&#xff0c;微软Office和WPS的其他套件也是如此操作。一、W…

uni-app项目gitignore文件示例

uni-app 忽略以下文件和目录 DS_Store 忽略 UniApp 编译生成的小程序相关目录 unpackage/ uni_modules/ 忽略编辑器自动生成的文件 idea/ vscode/ 忽略日志文件 logs/ 忽略临时文件 temp/ 忽略构建工具自动生成的文件 build/ 忽略 npm 安装的包文件 package-lock.json yarn.loc…

LeetCode 135:分糖果

LeetCode 135&#xff1a;分糖果问题本质与核心挑战 给定孩子的评分数组&#xff0c;需满足 “每个孩子至少1颗糖果&#xff0c;相邻评分高的孩子糖果更多”&#xff0c;求最少糖果总数。核心挑战&#xff1a; 相邻约束是双向的&#xff08;左→右和右→左都需满足&#xff09;…

【QT】安装与配置

个人主页&#xff1a;Guiat 归属专栏&#xff1a;QT 文章目录1. QT简介与准备工作1.1 什么是QT1.2 QT的版本选择1.3 系统要求检查2. QT安装方式详解2.1 官方在线安装器2.2 离线安装包2.3 包管理器安装3. Windows平台安装配置3.1 Windows安装步骤3.2 环境变量配置3.3 Visual Stu…