Spring 高级解析 07

文章目录

    • 1. Spring 概述(基本情况)
      • 1.1 Spring 的优势
      • 1.2 Spring 的核⼼结构
    • 2. 核⼼思想 IoC 和 AOP
      • 2.1 什么是IoC?
      • 2.2 什么是AOP
      • 2.3 AOP在解决什么问题
    • 3. Spring IoC ⾼级应⽤
      • 3.1 BeanFactory与ApplicationContext区别
        • 3.1.1 BeanFactory
        • 3.1.2 ApplicationContext
        • 3.1.3区别总结
      • 3.2 DI 依赖注⼊的注解实现⽅式
      • 3.3 常用注解
      • 3.4 lazy-Init 延迟加载
      • 3.5 FactoryBean 和 BeanFactory
        • 3.5.1 FactoryBean
      • 3.6 后置处理器
        • 3.6.1 BeanPostProcessor
        • 3.6.2 BeanFactoryPostProcessor
      • 3.7 循环依赖问题
      • 3.7.1 循环依赖处理机制
    • 4. Spring AOP ⾼级应⽤
    • 5. Spring 声明式事务的⽀持
      • 5.1 事务的四⼤特性

1. Spring 概述(基本情况)

Spring 是分层的 full-stack(全栈) 轻量级开源框架,以 IoC 和 AOP 为内核,提供了展现层 Spring MVC 和业务层事务管理等众多的企业级应⽤技术,还能整合开源世界众多著名的第三⽅框架和类库,已
经成为使⽤最多的 Java EE 企业应⽤开源框架。

1.1 Spring 的优势

  1. ⽅便解耦,简化开发 通过Spring提供的IoC容器,可以将对象间的依赖关系交由Spring进⾏控制,避免硬编码所造成的 过度程序耦合。⽤户也不必再为单例模式类、属性⽂件解析等这些很底层的需求编写代码,可以更 专注于上层的应⽤。
  2. AOP编程的⽀持 通过Spring的AOP功能,⽅便进⾏⾯向切⾯的编程,许多不容易⽤传统OOP实现的功能可以通过 AOP轻松应付。
  3. 声明式事务的⽀持 @Transactional可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式⽅式灵活的进⾏事务的管理,提⾼ 开发效率和质量。
  4. ⽅便程序的测试可以⽤⾮容器依赖的编程⽅式进⾏⼏乎所有的测试⼯作,测试不再是昂贵的操作,⽽是随⼿可做的 事情。
  5. ⽅便集成各种优秀框架Spring可以降低各种框架的使⽤难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、 Quartz等)的直接⽀持。 降低JavaEE API的使⽤难度 Spring对JavaEE API(如JDBC、JavaMail、远程调⽤等)进⾏了薄薄的封装层,使这些API的使⽤ 难度⼤为降低。

1.2 Spring 的核⼼结构

Spring是⼀个分层⾮常清晰并且依赖关系、职责定位⾮常明确的轻量级框架,主要包括⼏个⼤模块:

  1. 数据处理模块
  2. Web模块
  3. AOP(Aspect Oriented Programming)/Aspects模块
  4. Core Container模块
  5. Test 模块
    在这里插入图片描述
    Spring核⼼容器(Core Container) 容器是Spring框架最核⼼的部分,它管理着Spring应⽤中 bean的创建、配置和管理。在该模块中,包括了Spring bean⼯⼚,它为Spring提供了DI的功能。 基于bean⼯⼚,我们还会发现有多种Spring应⽤上下⽂的实现。所有的Spring模块都构建于核⼼
    容器之上。

2. 核⼼思想 IoC 和 AOP

2.1 什么是IoC?

IoC Inversion of Control (控制反转/反转控制),注意它是⼀个技术思想,不是⼀个技术实现
描述的事情:Java开发领域对象的创建,管理的问题 传统开发⽅式:⽐如类A依赖于类B,往往会在类A中new⼀个B的对象

IoC思想下开发⽅式:我们不⽤⾃⼰去new对象了,⽽是由IoC容器(Spring框架)去帮助我们实例化对
象并且管理它,我们需要使⽤哪个对象,去问IoC容器要即可
我们丧失了⼀个权利(创建、管理对象的权利),得到了⼀个福利(不⽤考虑对象的创建、管理等⼀系列 事情)

为什么叫做控制反转?

控制:指的是对象创建(实例化、管理)的权利
反转:控制权交给外部环境了(spring框架、IoC容器)

IoC解决对象之间的耦合问题

2.2 什么是AOP

AOP: Aspect oriented Programming ⾯向切⾯编程/⾯向⽅⾯编程 AOP是OOP的延续
从OOP说起OOP三⼤特征:封装、继承和多态 oop是⼀种垂直继承体系

2.3 AOP在解决什么问题

在不改变原有业务逻辑情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复

3. Spring IoC ⾼级应⽤

3.1 BeanFactory与ApplicationContext区别

BeanFactory 和 ApplicationContext 都是 Spring Framework 中用于管理和获取 Bean
对象的核心接口,它们之间有一些重要的区别。

3.1.1 BeanFactory

定义和作用:

BeanFactory 是 Spring 框架中最基础的接口,提供了 IoC (控制反转) 和 DI (依赖注入) 的核心功能。它负责实例化、配置和管理 Spring Bean。
它是 Spring IoC 容器的基础接口,定义了获取 Bean 的基本方法,如 getBean() 等。

延迟初始化:

BeanFactory 采用延迟初始化策略,即在第一次请求获取 Bean 时才会进行实例化和初始化。

功能简单:
功能相对较少,主要提供了 IoC 容器的基本功能,适用于对资源和性能有较高要求的环境。

典型实现类:
典型的 BeanFactory 实现类是 XmlBeanFactory,已在 Spring 5.x 中标记为过时,推荐使用 ApplicationContext 代替。

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
MyBean bean = (MyBean) beanFactory.getBean("myBean");
3.1.2 ApplicationContext

定义和作用:

ApplicationContext 是 BeanFactory 的子接口,它增加了更多的企业级功能。除了提供 BeanFactory 的所有功能外,还提供了更多的企业级特性,如国际化支持事件发布机制资源加载AOP 支持等。

预加载和缓存:
ApplicationContext 在启动时会预加载所有的单例 Bean,并且提供了更好的性能和内存管理,因为它会缓存所有的 Bean 实例。

功能丰富:
除了 BeanFactory 的功能外,还提供了更多的企业级特性,使得 Spring 应用程序更加易于开发和管理。

典型实现类:
典型的 ApplicationContext 实现类有 ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、AnnotationConfigApplicationContext 等。

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
MyBean bean = (MyBean) context.getBean("myBean");
3.1.3区别总结
  1. 延迟初始化 vs 预加载:

BeanFactory 采用延迟初始化,只在需要时才实例化 Bean。
ApplicationContext 在启动时会预加载所有的单例 Bean,并且可以提供更好的性能和内存管理。

  1. 功能范围:

BeanFactory 提供了基本的 IoC 容器功能。
ApplicationContext 在 BeanFactory 的基础上增加了更多的企业级特性,如事件发布、AOP 支持、国际化支持等。

  1. 适用场景:
    如果应用对性能要求较高,可以使用 BeanFactory。
    如果需要更多的企业级特性或者对性能要求不那么敏感,建议使ApplicationContext。

3.2 DI 依赖注⼊的注解实现⽅式

@Autowired(推荐使⽤) @Autowired为Spring提供的注解,需要导⼊包 org.springframework.beans.factory.annotation.Autowired。 @Autowired采取的策略为按照类型注⼊。
public class TransferServiceImpl { @Autowired private AccountDao accountDao;
}
如上代码所示,这样装配回去spring容器中找到类型为AccountDao的类,然后将其注⼊进来。这 样会产⽣⼀个问题,当⼀个类型有多个bean值的时候,会造成⽆法选择具体注⼊哪⼀个的情况, 这个时候我们需要配合着@Qualifier使⽤。
@Qualifier告诉Spring具体去装配哪个对象。

@Resource @Resource 注解由 J2EE 提供,需要导⼊包 javax.annotation.Resource。
@Resource 默认按照 ByName ⾃动注⼊。

@Resource 在 Jdk 11中已经移除,如果要使⽤,需要单独引⼊jar包

3.3 常用注解

@Configuration 注解,表名当前类是⼀个配置类
@ComponentScan 注解,替代 context:component-scan
@PropertySource,引⼊外部属性配置⽂件 @Import 引⼊其他配置类 @Value 对变量赋值,可以直接赋值,也可以使⽤ ${} 读取资源配置⽂件中的信息
@Bean 将⽅法返回对象加⼊ SpringIOC 容器

3.4 lazy-Init 延迟加载

Bean的延迟加载(延迟创建)
ApplicationContext 容器的默认⾏为是在启动服务器时将所有 singleton bean 提前进⾏实例化。提前 实例化意味着作为初始化过程的⼀部分,ApplicationContext 实例会创建并配置所有的singletonbean。

  1. 开启延迟加载⼀定程度提⾼容器启动和运转性能
  2. 对于不常使⽤的 Bean 设置延迟加载,这样偶尔使⽤的时候再加载,不必要从⼀开始该 Bean 就占 ⽤资源

3.5 FactoryBean 和 BeanFactory

BeanFactory接⼝是容器的顶级接⼝,定义了容器的⼀些基础⾏为,负责⽣产和管理Bean的⼀个⼯⼚, 具体使⽤它下⾯的⼦接⼝类型,⽐如ApplicationContext;此处我们重点分析FactoryBean

Spring中Bean有两种,⼀种是普通Bean,⼀种是⼯⼚Bean(FactoryBean),FactoryBean可以⽣成 某⼀个类型的Bean实例(返回给我们),也就是说我们可以借助于它⾃定义Bean的创建过程。

Bean创建的三种⽅式中的静态⽅法和实例化⽅法和FactoryBean作⽤类似,FactoryBean使⽤较多,尤其在Spring框架⼀些组件中会使⽤,还有其他框架和Spring框架整合时使⽤

3.5.1 FactoryBean
  1. 定义和作用:

FactoryBean 是一个接口,用于在 Spring 容器中定义和配置复杂的 Bean 实例化逻辑。它允许自定义 Bean 的实例化过程,而不受限于标准的构造函数或静态工厂方法。
实现 FactoryBean 接口的类必须实现 getObject() 方法,该方法返回一个由该工厂创建的实际 Bean 实例。

  1. 自定义 Bean 实例化过程:
    FactoryBean 提供了更高级别的控制和定制化,允许程序员在创建 Bean 实例时执行自定义逻辑。

  2. 实现步骤:
    创建一个实现 FactoryBean 接口的类,并实现 getObject() 方法,定义如何创建 Bean 实例。
    在 Spring 配置文件中声明该 FactoryBean 的 Bean 定义。

3.6 后置处理器

Spring提供了两种后处理bean的扩展接⼝,分别为 BeanPostProcessorBeanFactoryPostProcessor,两者在使⽤上是有所区别的。

3.6.1 BeanPostProcessor

在Bean对象实例化(并不是Bean的整个⽣命周期完成)之后可以使⽤BeanPostProcessor进⾏后置处理做⼀些事情

定义⼀个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进⾏处理。如果要对
具体的某个bean处理,可以通过⽅法参数判断,两个类型参数分别为Object和String,第⼀个参数是每
个bean的实例,第⼆个参数是每个bean的name或者id属性的值。所以我们可以通过第⼆个参数,来判断我们将要处理的具体的bean。

package com.xxx; 
import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.config.BeanPostProcessor; 
import org.springframework.stereotype.Component;
/** * @Author 应癫
* @create 2019/12/3 16:59 */
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() { System.out.println("BeanPostProcessor 实现类构造函数...");
}
@Override public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException { if("xxx".equals(beanName)) { System.out.println("BeanPostProcessor 实现类 postProcessBeforeInitialization ⽅法被调⽤中......"); }
return bean; }
@Override public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException { if("xxx".equals(beanName)) { System.out.println("BeanPostProcessor 实现类 postProcessAfterInitialization ⽅法被调⽤中......"); }
return bean; }
}
3.6.2 BeanFactoryPostProcessor

在BeanFactory初始化之后可以使⽤BeanFactoryPostProcessor进⾏后置处理做⼀些事情

BeanDefinition对象:我们在 XML 中定义的 bean标签,Spring 解析 bean 标签成为⼀个 JavaBean,
这个JavaBean 就是 BeanDefinition 注意:调⽤ BeanFactoryPostProcessor
⽅法时,这时候bean还没有实例化,此时 bean 刚被解析成BeanDefinition对象

package com.xxx; 
import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; importorg.springframework.beans.factory.config.ConfigurableListableBeanFactory; 
import org.springframework.stereotype.Component;
/** * @Author 应癫
* @create 2019/12/3 16:56 */
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() { System.out.println("BeanFactoryPostProcessor的实现类构造函数...");
}
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("BeanFactoryPostProcessor的实现⽅法调⽤中......");
}
}

3.7 循环依赖问题

循环依赖其实就是循环引⽤,也就是两个或者两个以上的 Bean 互相持有对⽅,最终形成闭环。⽐如A 依赖于B,B依赖于C,C⼜依赖于A。

在这里插入图片描述
Spring中循环依赖场景有:

  1. 构造器的循环依赖(构造器注⼊)
  2. Field 属性的循环依赖(set注⼊)

3.7.1 循环依赖处理机制

  1. 单例 bean 构造器参数循环依赖(⽆法解决)
  2. prototype 原型 bean循环依赖(⽆法解决)
  3. 单例bean通过setXxx或者@Autowired进⾏循环依赖

Spring 的循环依赖的理论依据基于 Java 的引⽤传递,当获得对象的引⽤时,对象的属性是可以延后设置的,但是构造器必须是在获取引⽤之前

Spring通过setXxx或者@Autowired⽅法解决循环依赖其实是通过提前暴露⼀个ObjectFactory对 象来完成的,简单来说ClassA在调⽤构造器完成对象初始化之后,在调⽤ClassA的setClassB⽅法之前就把ClassA实例化的对象通过ObjectFactory提前暴露到Spring容器中。

4. Spring AOP ⾼级应⽤

spring 实现AOP思想使⽤的是动态代理技术 默认情况下,Spring会根据被代理对象是否实现接⼝来选择使⽤JDK还是CGLIB。当被代理对象没有实现 任何接⼝时,Spring会选择CGLIB。当被代理对象实现了接⼝,Spring会选择JDK官⽅的代理技术,不过
我们可以通过配置的⽅式,让Spring强制使⽤CGLIB。

连接点:⽅法开始时、结束时、正常运⾏完毕时、⽅法异常时等这些特殊的时机点,我们称之为连接 点,项⽬中每个⽅法都有连接点,连接点是⼀种候选点

切⼊点:指定AOP思想想要影响的具体⽅法是哪些,描述感兴趣的⽅法 Advice增强:
第⼀个层次:指的是横切逻辑

第⼆个层次:⽅位点(在某⼀些连接点上加⼊横切逻辑,那么这些连接点就叫做⽅位点,描述的是具体 的特殊时机)

Aspect切⾯:切⾯概念是对上述概念的⼀个综合 Aspect切⾯= 切⼊点(@pointcut)+增强
= 切⼊点(锁定⽅法) + ⽅位点(锁定⽅法中的特殊时机)+ 横切逻辑

5. Spring 声明式事务的⽀持

5.1 事务的四⼤特性

  1. 原⼦性(Atomicity) 原⼦性是指事务是⼀个不可分割的⼯作单位,事务中的操作要么都发⽣,要么都 不发⽣。

从操作的⻆度来描述,事务中的各个操作要么都成功要么都失败

  1. ⼀致性(Consistency)
    事务必须使数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态。 例如转账前A有1000,B有1000。转账后A+B也得是2000。 ⼀致性是从数据的⻆度来说的,(1000,1000) (900,1100),不应该出现(900,1000)

  2. 隔离性(Isolation)
    事务的隔离性是多个⽤户并发访问数据库时,数据库为每⼀个⽤户开启的事务, 每个事务不能被其他事务的操作数据所⼲扰,多个并发事务之间要相互隔离。
    ⽐如:事务1给员⼯涨⼯资2000,但是事务1尚未被提交,员⼯发起事务2查询⼯资,发现⼯资涨了2000 块钱,读到了事务1尚未提交的数据(脏读)

  3. 持久性(Durability)
    持久性是指⼀个事务⼀旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发⽣故障也不应该对其有任何影响。

@EnableTransactionManagement

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

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

相关文章

Android虚假定位的实现与防护

Android中常用的定位方式 一,GPS定位 定义:全球卫星定位系统,直接和卫星交互,获取设备经纬度 优点: 走卫星通信通道,无需打开Wifi或流量就能获得位置信息 精确度最高,几米到几十米 缺点&a…

Java面试八股之Spring AOP 和 AspectJ AOP 的区别

Spring AOP 和 AspectJ AOP 的区别 Spring AOP 和 AspectJ AOP 是两种不同的面向切面编程(Aspect-Oriented Programming, AOP)实现。它们各有特点,适用于不同的场景。下面是一些主要的区别: 1. 实现机制 Spring AOP: 基于代理…

为Mac配置Alfred

参考资料: Alfred神器使用手册 | louis blogMacOS神器之Alfred workflow概览GitHub - arpir/Alfred-Workflows-Collection: 一些好用的 Alfred Workflow 一、修改快捷键 Spotlight的默认快捷键是Command Space Alfred的默认快捷键是Option Space 可以将Alfred和…

Alternating Sum

Problem - 963A - Codeforces 处理式子 显然中间式子是等比数列 // Problem: A. Alternating Sum // Contest: Codeforces - Tinkoff Internship Warmup Round 2018 and Codeforces Round 475 (Div. 1) // URL: https://codeforces.com/problemset/problem/963/A // Memory Lim…

awk用法

文章目录 一、awk工具awk工作原理AWK程序的结构awk内置变量 二、案例1.基础案列2.BEGIN END 运算3.数值与字符串的比较4.awk高级用法5. awk if语句6.BEGIN END 流程7.AWK 数组8.awk 循环 一、awk工具 awk工作原理 当读到第一行时,匹配条件,然后执行指定…

【C++11】C++11新纪元:深入探索右值引用与移动语义

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C “ 登神长阶 ” 🤡往期回顾🤡:位图与布隆过滤器 🌹🌹期待您的关注 🌹🌹 ❀C11 📒1. C11简介…

【Qt】修改窗口的标题和图标

以下操作仅对顶层 widget(独⽴窗口),有效。 修改窗口的标题 一.windowTitle属性 1.概念 是一种在用户界面中显示窗口的标题的属性。它可以用来设置窗口的标题栏文本。 2.API API说明windowTitle()获取到控件的窗⼝标题.setWindowTitle(const QString& title)设置控件的…

10 BERT

目录 1 综述 1.1 BERT的核心思想 1.2 BERT的关键技术:预训练阶段 1.3 微调阶段 2 BERT的架构 2.1 输入处理 3. 特征选择/学习模块 BERT 的自注意力过程 4. 预训练任务:同时进行 4.1 Next Sentence Prediction (NSP) 4.2 Masked Language Model…

基于微信小程序+SpringBoot+Vue的网络安全科普系统(带1w+文档)

基于微信小程序SpringBootVue的网络安全科普系统(带1w文档) 基于微信小程序SpringBootVue的网络安全科普系统(带1w文档) 优质的网络安全科普系统不仅可以单纯的满足工作人员管理的日常工作需求,还可以满足用户的需求。可以降低工作人员的工作压力,提高效…

2024.7.29 作业

1> 写一个日志文件&#xff0c;将程序启动后&#xff0c;每一秒的时间写入到文件中 #include <myhead.h> int main(int argc,const char *argv[]) {FILE *fp NULL;if((fpfopen("./log.txt","r"))NULL) {perror("open error1");return…

Python数值计算(1)

准备总结一下通过Python进行数值计算的环境&#xff0c;先说一下数值计算的基本语法和库。 1.基本运算 Python中提供基本运算符&#xff0c;常见的加减乘除&#xff0c;唯一需要注意的是除法&#xff0c;整数除法和浮点数除法不一样。 一般除法/&#xff0c;无论参与运算的数…

通信系统的均衡技术

1、摘要 在通信系统中&#xff0c;信号从发送端发出&#xff0c;经过信道&#xff0c;到达接收端&#xff0c;而在传输的过程中&#xff0c;信号会发生失真&#xff0c;产生失真的原因有很多&#xff0c;包括阻抗不匹配&#xff0c;干扰等。为了优化信号质量&#xff0c;需要进…

基于tkinter的学生信息管理系统之登录界面和主界面菜单设计

目录 一、tkinter的介绍 二、登陆界面的设计 1、登陆界面完整代码 2、部分代码讲解 3、登录的数据模型设计 4、效果展示 三、学生主界面菜单设计 1、学生主界面菜单设计完整代码 2、 部分代码讲解 3、效果展示 四、数据库的模型设计 欢迎大家进来学习和支持&#xff01…

灯具外贸公司用什么企业邮箱好

灯具外贸公司面对海外市场的推广、产品销售、客户沟通、市场信息收集等多重需求&#xff0c;选择一个合适的企业邮箱显得尤为重要。本文将介绍灯具外贸公司为什么应选择Zoho Mail企业邮箱&#xff0c;并详细探讨其优势和功能。 一、公司背景 广东省深圳市光明新区&#xff0c…

Redis 安装和数据类型

Redis 安装和数据类型 一、Redis 1、Redis概念 redis 缓存中间件&#xff1a;缓存数据库 nginx web服务 php 转发动态请求 tomcat web页面&#xff0c;也可以转发动态请求 springboot 自带tomcat 数据库不支持高并发&#xff0c;一旦访问量激增&#xff0c;数据库很快就…

vTESTstudio中如何添加DLL文件?

文章目录 一、CANoe添加DLL二、vTESTstudio中添加DLL1.手动添加2.代码添加 一、CANoe添加DLL 在CANoe中添加DLL的路径如下图&#xff0c;在Simulation Setup中选择需要添加的节点&#xff0c;右键选择Configuration进行添加DLL。 二、vTESTstudio中添加DLL 1.手动添加 在打…

java中 VO DTO BO PO DAO

VO、DTO、BO、PO、DO、POJO 数据模型的理解和实际使用_vo dto bo-CSDN博客 深入理解Java Web开发中的PO、VO、DTO、DAO和BO概念_java dto dao-CSDN博客

【计算机网络】WireShark和简单http抓包实验

一&#xff1a;实验目的 1&#xff1a;熟悉WireShark的安装流程和界面操作流程。 2&#xff1a;学会简单http的抓取和过滤&#xff0c;并分析导出结果。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a; Windows 2019操作系统的计算机等。 软件&#xff1a;WireShark、…

【算法/训练】:动态规划(线性DP)

一、路径类 1. 字母收集 思路&#xff1a; 1、预处理 对输入的字符矩阵我们按照要求将其转换为数字分数&#xff0c;由于只能往下和往右走&#xff0c;因此走到&#xff08;i&#xff0c;j&#xff09;的位置要就是从&#xff08;i - 1&#xff0c; j&#xff09;往下走&#…