一 Spring-AOP

1.对SpringAOP理解

        AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低提高程序的可重用性,同时提高了开发的效率。

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

SpringAOP基于动态代理实现:

  •         如果被代理的对象,已经实现某个接口,则SpringAOP会使用JDK Proxy(反射),基于接口的方式,创建代理对象(JDK动态代理的核心是InvocationHandler接口和Proxy类);
  •         如果被代理的对象,没有实现某个接口,就无法使用JDK Proxy去处理代理了,这时候Spring会使用Cglib,基于继承的方式,生成一个被代理类对象的子类来作为代理(Cglib动态代理的核心是MethodInterceptor接口和Enhancer类)。

2.AOP通知

        概念:AOP将抽取出来的共性功能称为通知;

        通知类型:以通知在上下文中的具体位置作为划分

        解释:通知就是需要增强的方法内容以及执行位置的结合。

        前置通知-before,返回通知-after-returning,异常通知-after-throwing,后置通知-after,环绕通知-around.

<!--    aop配置--><aop:config>
<!--        配置切面--><aop:aspect id="mian" ref="logger">
<!--            配置切点--><aop:pointcut id="cut" expression="execution(public * com.itheima.service.*.*(..))"></aop:pointcut>
<!--            配置通知-->
<!--            前置通知--><aop:before method="beforeLog" pointcut-ref="cut"></aop:before>
<!--            后置通知--><aop:after method="afterLog" pointcut-ref="cut"></aop:after>
<!--            返回通知--><aop:after-returning method="afterReturningLog" pointcut-ref="cut"></aop:after-returning>
<!--            异常通知--><aop:after-throwing method="afterThrowingLog" pointcut-ref="cut"></aop:after-throwing><aop:around method="aroundLog" pointcut-ref="cut"></aop:around></aop:aspect></aop:config>

3.AOP连接点

        AOP将所有的方法都视为连接点,不管是接口里面的抽象方法,还是实现类里面的重写方法,都是连接点。

        解释:具备添加通知能力的方法位置,就是连接点,也就是所有类的所有方法

4.AOP切点

        AOP将可能被抽取共性功能的方法称为切入点,切入点是连接点的子集。

        解释:成功添加了通知方法的位置,就是切点。

<aop:pointcut id="dian" expression="execution(public * com.apesource.service.*.*(..))"/>

5.AOP目标对象

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

        解释:被代理对象,就是目标对象

6.AOP织入

        就是将挖掉的功能回填的动态过程

        解释:将通知添加到切点的过程ing,就是织入。

补充:AOP切面:切点+通知


7.SpringAOP+AspectJ实现

        1.坐标

        <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.7</version></dependency>

        2.配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="accountSErviceImp" class="com.itheima.service.AccountServiceImp"></bean><bean id="logger" class="com.itheima.util.Logger"></bean>
<!--    aop配置--><aop:config>
<!--        配置切面--><aop:aspect id="mian" ref="logger">
<!--            配置切点--><aop:pointcut id="cut" expression="execution(public * com.itheima.service.*.*(..))"></aop:pointcut>
<!--            配置通知-->
<!--            前置通知--><aop:before method="beforeLog" pointcut-ref="cut"></aop:before>
<!--            后置通知--><aop:after method="afterLog" pointcut-ref="cut"></aop:after>
<!--            返回通知--><aop:after-returning method="afterReturningLog" pointcut-ref="cut"></aop:after-returning>
<!--            异常通知--><aop:after-throwing method="afterThrowingLog" pointcut-ref="cut"></aop:after-throwing><aop:around method="aroundLog" pointcut-ref="cut"></aop:around></aop:aspect></aop:config>
</beans>

切点表达式配置语法

        execution(修饰符 返回值 包名称.类名称.方法名称(参数列表))

1.修饰符可以省略代表任意
execution(返回值 包名称.类名称.方法名称(参数列表))
2.返回值可以使用“*”代表任意
execution(* 包名称.类名称.方法名称(参数列表))
3.包名可以使用“*”代表任意名称
execution(* *.*.*.类名称.方法名称(参数列表))
eg:execution(void *.*.*.ServiceImp.findAll())
4.包名可以使用“..”代表任意个数
execution(* *..类名称.方法名称(参数列表))
eg:execution(void *..ServiceImp.findAll())
5.类名与方法名可以使用“*”代表任意
execution(* *...*.*(参数列表))
6.参数列表可以使用".."代表任意个数任意类型
execution(* *...*.*(..))

    如果有参数
int======>int
String===>java.lang.String

二 Spring中bean的一生

1.bean实例化的基本流程-底层

        Spring容器在进行初始化时,会将xml配置的信息封装成一个BeanDefinition对象,所有的BeanDefinition存储到一个名为beanDefinitionMap的Map集合中去,Spring框架在对该Map进行遍历,使用反射创建bean实例对象,创建号的Bean对象存储在一个名为singletonObject的Map集合中,当调用getBean方法时,则最终从该Map集合中取出Bean实例对象返回。

  Bean 实例化的基本流程

加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的BeanDefinition对象;

BeanDefinition存储在一个名为beanDefinitionMap的Map中;

ApplicationContext底层遍历beanDefinitionMap,创建Bean实例对象; 创建好的Bean实例对象,被存储到一个名为singletonObjects的Map中;

当执行applicationContext.getBean(beanName)时,从singletonObjects去匹配Bean实例返回。

2.Spring 还有其他类型的 “后处理器”

后处理器接口作用阶段核心功能
BeanFactoryPostProcessorBean 定义加载后,Bean 实例化前修改 BeanDefinition(Bean 的元信息),例如:
- 动态修改 Bean 的属性值、作用域
- 新增 Bean 定义(如 Spring 的PropertyPlaceholderConfigurer用于解析${}占位符)
BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor 的增强版,更早执行向容器中注册新的 BeanDefinition(比BeanFactoryPostProcessor有更高的优先级),例如:
- 动态扫描并注册 Bean(Spring Boot 的 @ComponentScan 底层用到类似机制)
InstantiationAwareBeanPostProcessorBean 实例化前后(比BeanPostProcessor更早)干预 Bean 的实例化过程,例如:
- 阻止默认实例化,返回自定义 Bean 对象
- 处理属性注入前的逻辑(如 @Autowired 的依赖查找)
DestructionAwareBeanPostProcessorBean 销毁前处理 Bean 销毁前的逻辑,例如:
- 资源释放、状态清理等

Spring的后处理器是Spring对外开放的重要扩展点,允许我们介入到Bean的整个实例化流程中来,以达到动态注册BeanDefinition,以及动态修改Bean的作用。

Spring主要有两种后处理器

  •         BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例话之前执行;
  • BeanPostProcessor:Bean后处理器,一般在Bean实例化之后,填充到单例池singletonObjects之前执行;

3.Bean工厂后处理器 – BeanFactoryPostProcessor

BeanFactoryPostProcessor是一个接口规范,实现了该接口的类只要交由Spring容器管理的话,那么 Spring就会 回调该接口的方法,用于对BeanDefinition注册和修改的功能。

修改

        1. 创建BeanFactoryPostProcessor实现类并重写方法

        2. 注入实现类

注册

        1. 创建BeanFactoryPostProcessor实现类并重写方法

        2. 注入实现类

Spring 提供了一个BeanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor专门用 于注册BeanDefinition操作

public class MyBeanFactoryPostProcessor2 implements 
BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory 
configurableListableBeanFactory) throws BeansException {}@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry 
beanDefinitionRegistry) throws BeansException {BeanDefinition beanDefinition = new RootBeanDefinition();beanDefinition.setBeanClassName("com.apesource.pojo.Student");beanDefinitionRegistry.registerBeanDefinition("stu",beanDefinition);}
}

4.Bean后处理器-BeanPostProcessor

        Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过Bean的初始化过程。

public class MyBeanPostProcessor implements BeanPostProcessor{public Object postProcessBeforeInitialization(Object bean, String beanName){System.out.println("初始化之前执行");return bean;}public Object postProcessAfterInitialization(Object bean, String beanName){System.out.println("初始化之后执行");return bean;}

5.spring-bean的生命周期

        从Bean实例化之后,及通过反射创建出对象之后,到Bean成为一个完整对象最终存储到单例池中,这个过程被成为SPringBean的生命周期。

大致分为三个阶段

  • Bean的实例化阶段:spring框架会取出BeanDefinition的信息进行判断当前bean的范围是否是singleton的,是否不是延迟加载的,是否不是FactoryBean等,最终将一个普通的singleton的Bean通过反射进行实例化。
  • Bean的初始化阶段:Bean创建之后还仅仅是个”半成品“,还需要对Bean的实例进行填充,执行一些aware接口方法,执行BeanPostProcessor方法,执行InitializingBean接口的初始化方法。执行自定义初始化init方法等。该阶段是Spring最具技术含量和复杂度的阶段。
  • Bean的完成阶段:经过初始化阶段,Bean就成为了一个完整的Spring Bean,被存储到单例池sinletonObjects去了,及完成了SPringBean的整个生命周期。

6.Spring Bean的初始化过程涉及如下几个过程:

  • Bean实例的属性填充

  • Aware接口属性注入

  • BeanPostProcessorbefore()方法回调

  • InitializingBean接口的初始化方法回调 自定义初始化方法init回调

  • BeanPostProcessorafter()方法回调

8.常用的Aware接口

        Aware接口是一种框架辅助属性注入的一种思想,其他框架中也可以看到类似的接口。框架具备高度封装性,我们接 触到的一般都是业务代码,一个底层功能API不能轻易的获取到,但是这不意味着永远用不到这些对象,如果用到了 ,就可以使用框架提供的类似Aware的接口,让框架给我们注入该对象。

三 循环依赖-解决

      1.  Spring在进行属性注入时,会分为如下几种情况:

                注入普通属性,String、int或存储基本类型的集合时,直接通过set方法的反射设置进去;

                注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没有,则先创建被注入对象Bean实例(完成整个生命周期)后,在进行注入操作;

                注入双向对象引用属性时,就比较复杂了,涉及了循环引用(循环依赖)。

循环依赖

        含义:多个实体之间相互依赖并形成闭环的情况就叫做"循环依赖",也叫做"循环引用"。

        Spring提供了 三级缓存 存储完整Bean实例半成品Bean实例,用于解决循环引用问题

        在DefaultListableBeanFactory的上四级父类DefaultSingletonBeanRegistry中提供如下三个Map

public class DefaultSingletonBeanRegistry ... {//1、最终存储单例Bean成品的容器,即实例化和初始化都完成的Bean,称之为"一级缓存"    Map<String, Object> singletonObjects = new ConcurrentHashMap(256);//2、早期Bean单例池,缓存半成品对象,且当前对象已经被其他对象引用了,称之为"二级缓存"    Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);//3、单例Bean的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建Bean,称之为"三级缓存"    
Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
}

注:将对象保存至三级缓存的时候,会包装成ObjectFactory对象录入,未来通过此接口对应的get方法再次提取对象.

UserService和UserDao循环依赖的过程结合上述三级缓存描述一下

  1. UserService 实例化对象,但尚未初始化,将UserService存储到三级缓存
  2. UserService 属性注入,需要UserDao,从缓存中获取,没有UserDao
  3. UserDao实例化对象,但尚未初始化,将UserDao存储到到三级缓存;
  4. UserDao属性注入,需要UserService,从三级缓存获取UserService,UserService三级缓存移入二级缓存
  5. UserDao执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存; UserService 注入UserDao;
  6. UserService执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存。

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

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

相关文章

大数据与AI:一场“数据盛宴”与“智能大脑”的奇妙邂逅

在当今这个信息爆炸的时代&#xff0c;大数据和AI&#xff08;人工智能&#xff09;就像一对热恋中的情侣&#xff0c;天天黏在一起&#xff0c;形影不离。它们的结合&#xff0c;不仅改变了我们的生活方式&#xff0c;还让这个世界变得更加有趣和奇妙。今天&#xff0c;就让我…

解决window下共享资源报“不允许一个用户使用一个以上用户名与服务器或共享资源的多重连接“问题

问题现象&#xff1a; 使用不同samba共享账号登录同一服务器ip共享文件夹资源时会报错误提示解决办法&#xff1a; 1.使用net use命令查看已保存的网络连接 C:\Users\Administrator>net use 会记录新的网络连接。状态 本地 远程 网络----…

SciKit-Learn 全面分析分类任务 wine 葡萄酒数据集

背景 wine 葡萄酒数据集&#xff0c;提供了对三种不同品种的意大利葡萄酒的化学分析结果 主要特点&#xff1a; 数据集规模&#xff1a;总共有 178 个样本特征数量&#xff1a;每个样本有 13 个化学特征&#xff0c;包括酒精、苹果酸、灰分、镁等类别数量&#xff1a;总共有 3 …

【论文阅读】Far3D: Expanding the Horizon for Surround-view 3D Object Detection

标题&#xff1a; Far3D: Expanding the Horizon for Surround-view 3D Object Detection motivation 作者觉得市面上的方法对远处的long-range 的3d-od检测没有深入研究&#xff0c;于是作者提出FAR3D. 基于环视图像的3D物体检测取得了显著进展&#xff0c;且其部署成本较低。…

Redis分布式锁的try-with-resources实现

Redis分布式锁的try-with-resources实现 在Java中&#xff0c;try-with-resources是一种自动资源管理机制&#xff0c;适用于实现了AutoCloseable接口的类。通过结合Redis分布式锁和try-with-resources&#xff0c;可以确保锁的自动释放&#xff0c;避免因异常或忘记释放锁导致…

上传文件接口设计,SpringBoot + MinIO/S3 文件服务实现:FileService 接口与 FileServiceImpl 详解

在企业项目中&#xff0c;文件上传和管理是非常常见的需求。本文基于 芋道源码 的实现&#xff0c;介绍如何封装一个通用的 文件服务 FileService&#xff0c;支持&#xff1a;文件上传&#xff08;保存数据库记录 存储文件到 S3/MinIO 等对象存储&#xff09;文件下载与删除文…

MVC 依赖注入(DI)与服务全解析(附避坑实战)

依赖注入的核心概念 依赖注入&#xff08;DI&#xff09;是一种设计模式&#xff0c;通过将对象的依赖关系从内部创建转移到外部传递&#xff0c;实现解耦。在 MVC 框架中&#xff0c;DI 容器负责管理对象的生命周期和依赖关系&#xff0c;开发者只需声明依赖&#xff0c;容器…

【实证分析】上市公司经营风险数据集-含代码(2000-2022年)

数据简介&#xff1a;上市公司经营风险涉及多维度、多层次的复杂因素&#xff0c;本文章参考王竹泉-经营风险与营运资金融资决策对上市公司经验风险进行测算&#xff0c;经营风险是该公司息税折旧摊销前利润率的标准差&#xff0c;经营风险是该公司息税折旧摊销前利润率的标准差…

领码方案|Windows 下 PLT → PDF 转换服务超级完整版:异步、权限、进度

摘要 面向 Windows 平台&#xff0c;使用 ASP.NET Core Web API 结合 Ghostscript.NET 库&#xff0c;实现 PLT&#xff08;HPGL&#xff09;→PDF 的纯库调用转换&#xff0c;无需外部进程。支持同步与异步模式&#xff0c;采用 JWTRBAC 进行权限治理&#xff0c;任务状态存储…

浏览器兼容性问题全解:CSS 前缀、Grid/Flex 布局兼容方案与跨浏览器调试技巧

1. 浏览器兼容性与前缀问题 不同浏览器&#xff08;尤其是老版本 IE、Edge、Safari&#xff09;对新特性&#xff08;比如 CSS 变量、Grid、Flex 等&#xff09;的支持程度不一&#xff0c;需要使用厂商前缀&#xff08;-webkit-、-moz- 等&#xff09;或降级方案。新手往往忽…

【Android View】事件分发机制

参考文献 https://juejin.cn/post/6844904041487532045https://juejin.cn/post/6844903894103883789#heading-12https://www.jianshu.com/p/dea72779a6b7 文章目录

【大数据相关】ClickHouse命令行与SQL语法详解

ClickHouse命令行与SQL语法详解一、ClickHouse命令行与SQL语法详解第一部分&#xff1a;ClickHouse SQL 命令行客户端 (clickhouse-client)1. 基础连接2. 核心命令行参数3. 数据导入与导出实战第二部分&#xff1a;ClickHouse SQL 语法详解1. DDL (数据定义语言)2. DML (数据操…

学习日记-CSS-day53-9.11

1.CSS介绍知识点核心内容重点CSS定义层叠样式表&#xff0c;用于内容修饰和样式展现英文全称cascading style sheetsCSS作用实现HTML内容与样式分离&#xff0c;提高开发效率对比传统HTML元素单独设置样式的低效方式学习建议掌握常用功能即可&#xff0c;重点在打通前后端数据通…

Maven中optional的作用

目的&#xff1a; 控制依赖传递 &#xff1a;将依赖标记为可选&#xff0c;这样当其他模块依赖common-component时&#xff0c;不会自动继承Elasticsearch依赖。这遵循了"依赖最小化"原则&#xff0c;避免不必要的库被引入到不需要它们的模块中。模块化设计 &#xf…

蓝桥杯算法之基础知识(7)---排序题的快排和归并排序

一、快排》快排方法&#xff0c;就三步1.随便选一个值作为基准值x2.拿选中的这个x值划分队列为左右两个区间&#xff08;左边的都小于x&#xff0c;右边的都大于x&#xff09;3.然后递归左区间和右区间就行》代码举例&#xff1a;#qs排序#1 6 7 8 6 5 4 #先找比较点&#xff0c…

缓存未命中

缓存未命中&#xff08;Cache Miss&#xff09; 发生在 CPU 访问某块内存时&#xff0c;该地址不在当前缓存&#xff08;L1/L2/L3&#xff09;中&#xff0c;导致程序被迫从更慢的内存&#xff08;RAM&#xff09;读取数据&#xff0c;严重拖慢程序执行速度。 &#x1f4cd; 一…

AR眼镜:化工安全生产的技术革命

在石化企业的压缩机组巡检中&#xff0c;佩戴AR眼镜的巡检员眼前实时显示着设备温度场分布和振动频谱曲线&#xff0c;单台设备巡检时间从45分钟缩短至18分钟。这不仅是效率的提升&#xff0c;更是化工安全生产的一场智能革命。一、行业痛点&#xff1a;传统化工巡检的困境与挑…

消息中间件RabbitMQ(从入门到精通)

RabbitMQ概念_MQ 消息队列 MQ全称Message Queue(消息队列),是在消息的传输过程中保存消息的容器。多用于系统之间的异步通信。 同步通信相当于两个人当面对话,你一言我一语。必须及时回复 异步通信相当于通过第三方转述对话,可能有消息的延迟,但不需要二人时刻保持联系。…

前端学习之后端java小白(五)之多表查询/事务

一、多表查询概念二、概述 1. 内连接隐式内连接 SELECT 字段列表 FROM 表1&#xff0c;表2... WHERE 条件显示内连接SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 条件2. 外连接 左外连接SELECT 列名 FROM 左表 LEFT [OUTER] JOIN 右表 ON 连接条件;右外连接SELECT 列名…

Java全栈学习笔记34

# JDBCjava database connection Java 数据库连接技术## JDBC 驱动程序如果需要通过jdbc技术连接关系型数据库&#xff0c;就需要为jdbc提供一个该数据库的驱动。驱动程序由对应的数据库厂商提供。mysql提供了针对于各种语言的驱动程序。去官网下载和java相关的驱动即可## JDB…