一. Spring核心功能
**依赖注入(DI):**Spring的核心功能是通过依赖注入来管理对象之间的依赖关系。依赖注入是一种将对象的依赖关系注入到被依赖对象中的机制,它可以帮助降低对象之间的耦合度,使得代码更容易维护和测试。
**控制反转(IoC):**IoC是Spring框架的核心思想之一。Spring的IoC容器管理和协调应用程序中的对象,而不是通过应用程序代码显式创建和依赖对象。Spring容器负责创建、配置和管理应用程序中的对象生命周期。它使用XML、注解或Java代码来定义和配置对象之间的依赖关系。通过使用IoC容器,开发人员可以更加专注于业务逻辑的实现,而不必关注对象的创建和依赖关系的维护。
**面向切面编程(AOP):**Spring提供了面向切面编程的支持,使得开发人员可以更方便地将与业务逻辑无关的代码(如日志记录、事务管理等)进行解耦。通过AOP,开发人员可以将这些横切关注点进行统一管理,从而提高代码的可维护性和可测试性。
**声明式事务管理:**Spring提供了一种声明式事务管理的机制,使开发人员能够以声明的方式管理事务。通过配置事务管理器和事务属性,开发人员可以轻松地对数据库操作进行事务管理,而无需编写复杂的事务管理代码。
**数据访问抽象:**Spring提供了一套数据访问抽象,使得开发人员可以更方便地与不同的数据访问技术进行交互。无论是使用关系型数据库还是非关系型数据库,开发人员都可以通过Spring提供的数据访问抽象来统一访问数据。
**Spring MVC框架:**Spring提供了一个基于MVC模式的Web框架,使得开发人员能够更轻松地开发和管理Web应用程序。Spring MVC框架提供了一套灵活而强大的机制来处理Web请求和生成响应,同时还提供了一些常用的功能,如表单处理、数据绑定、文件上传等。
总的来说,Spring的核心是一个轻量级的容器,它提供了依赖注入、面向切面编程、声明式事务管理、数据访问抽象和MVC框架等核心功能,这些功能使得开发人员可以更方便地开发和管理Java应用程序。
二. Spring与SpringBoot区别
- Spring是一个全面的框架,提供了一套丰富的功能来处理企业级应用开发中的各个方面,包括依赖注入、事务管理、安全性等。而Spring Boot旨在简化复杂性,通过自动配置和约定大于配置的原则,让开发者能够快速地构建应用程序。
- Spring需要大量的XML或Java配置来完成各种任务,而Spring Boot通过自动配置大大减少了这部分工作。
- Spring Boot使用嵌入式的Tomcat或Jetty服务器,与应用程序一起打包,无需部署,这使得启动速度相对较快。
- Spring Boot使用"Starter"来简化Maven配置,可以快速地添加各种功能和库。
- Spring Boot专为构建微服务应用程序而设计。
详细解释Spring和SpringBoot的区别:
- 配置 :
- Spring:需要大量的XML或Java配置来完成各种任务。
- Spring Boot:通过自动配置大大减少了配置工作,使得开发者可以专注于应用程序本身而不是配置。
- 启动速度 :
- Spring:使用传统的服务器,需要部署。
- Spring Boot:使用嵌入式的Tomcat或Jetty服务器,与应用程序一起打包,无需部署,启动速度相对较快。
- 依赖管理 :
- Spring:需要开发者手动管理依赖。
- Spring Boot:使用"starters"来简化Maven配置,可以快速地添加各种功能和库。
**三.**Spring与SpringMVC区别
- SpringMVC是Spring框架中的一个模块,专注于Web应用程序的开发。它实现了模型-视图-控制器(MVC)设计模式,旨在简化Web应用的开发。SpringMVC处理Web请求,将请求映射到相应的处理器(Controller),处理器执行相应的业务逻辑,然后返回模型数据给视图层进行渲染。SpringMVC提供了丰富的注解支持,简化了配置过程,使得开发者可以快速开发出高效的Web应用。
- Spring是一个全面的企业应用开发框架,提供了包括Web开发在内的多种功能;而SpringMVC是Spring框架中的一个模块,专注于简化Web应用的开发,特别是通过实现MVC模式来处理Web请求。
四. SpringBoot与SpringCloud区别
- SpringBoot 是一个快速开发框架,它简化了传统MVC的XML配置,使配置变得更加方便、简洁。
- SpringCloud 是建立在SpringBoot上的服务框架,进一步简化了配置,它整合了一全套简单、便捷且通俗易用的框架,
- **Eureka(服务治理):**Eureka是Spring Cloud的服务治理组件,主要用于实现服务的注册与发现。通过Eureka,我们可以将微服务实例注册到中心化的服务注册表,并实现自动发现和动态负载均衡。Eureka支持高可用和可扩展的特性,能够有效地管理服务实例的故障转移和水平扩展。
- **Ribbon(负载均衡):**Ribbon是一个客户端负载均衡器,它提供了简单而强大的负载均衡功能。Ribbon可以与Eureka等服务发现组件集成,自动从服务注册表中获取服务实例的地址,并基于一定的算法进行负载均衡。这使得开发者能够更加专注于业务逻辑的实现,而不必花费过多精力在服务调用的细节上。
- **Hystrix(断路器):**Hystrix是Spring Cloud的断路器组件,主要用于防止级联故障和延迟。当某个服务出现故障时,Hystrix可以快速地切断对该服务的调用,从而避免故障的扩散。同时,Hystrix还提供了延迟容忍和容错机制,能够在网络延迟或服务故障时自动降级,保证系统的可用性和稳定性。
- **Zuul(网关):**Zuul是Spring Cloud的API网关组件,它提供了一种简单而有效的方式来管理和保护微服务的API接口。通过Zuul,我们可以将所有的API请求统一接入,进行安全认证、请求路由、负载均衡、熔断降级等操作。Zuul还支持动态路由和过滤器机制,可以根据实际需求进行自定义配置。
- **Config(配置中心):**Config是Spring Cloud的配置中心组件,它提供了一种集中式管理配置的方法。通过Config,我们可以将所有的配置信息统一存储在中心化的配置中心中,并动态地更新微服务的配置信息。这使得我们可以更加灵活地管理和维护微服务的配置信息,避免了配置不一致和重复配置的问题。
五. SpringCloud微服务组件
- **注册发现中心(Eureka,Nacos,Zookeeper,Consul):**它的作用是将同一个项目中的各个微服务注册到一起,从而使它们间相互认识。
- **服务调用负载(Ribbon,LoadBalancer):**Ribbon 可以在多个服务实例之间分配请求,以平衡负载并避免任何单个实例过载。
- 熔断器(Hystrix,Sentinel)。它的作用是当某个微服务瘫痪时可以将它从调用链中踢除出去,从而保证调用链上其他微服务的正常运作。
- 调用中心(Fegin,Open Feign)。它的作用是将各个微服务联系起来,使它们之间可以实现相互调用,由此组合成一个整体。
- 微服务网关(Zuul,GateWay)。它的作用是为不同的微服务提供一个统一的访问端口。
- 云配置中心(Cloud Config,Nacos)。它的作用是将一个项目所需的配置文件都放到云端统一管理,从而做到一个项目只有一套配置文件。
- 消息总线(Cloud Bus,Nacos)。它的作用是在修改配置文件时,可以在不停止服务运行的情况下重新加载配置。
六. Spring Bean生命周期
大致分为五个阶段:
实例化 Bean
对 Bean 当中的属性进行赋值
初始化 Bean
使用 Bean
销毁 Bean
详细阶段:
Bean元信息配置阶段
Bean元信息解析阶段
将Bean注册到容器中
BeanDefinition合并阶段
Bean Class加载阶段
Bean实例化阶段(2个小阶段)
Bean实例化前阶段
Bean实例化阶段
合并后的BeanDefinition处理
属性赋值阶段(3个小阶段)
Bean实例化后阶段
Bean属性赋值前阶段
Bean属性赋值阶段
- Bean初始化阶段(5个小阶段)
Bean Aware接口回调阶段
Bean初始化前阶段
Bean初始化阶段
Bean初始化后阶段
所有单例bean初始化完成后阶段
Bean的使用阶段
Bean销毁前阶段
Bean销毁阶段
1. Bean元信息配置阶段
1.1. Bean定义4种方式
1.1.1. API方式
Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构,不管是是通过xml配置文件的<Bean>标签,还是通过注解配置的@Bean,还是@Compontent标注的类,还是扫描得到的类,它最终都会被解析成一个BeanDefinition对象,最后我们的Bean工厂就会根据这份Bean的定义信息,对bean进行实例化、初始化等等操作。
1.1.2. Xml文件方式
Xml中的bean配置信息会被解析器解析为BeanDefinition对象,一会在第二阶段详解。
1.1.3. Properties文件的方式
将bean定义信息放在properties文件中,然后通过解析器将配置信息解析为BeanDefinition对象。
java
employee.(class)=MyClass // 等同于:<bean class="MyClass" />
employee.(abstract)=true // 等同于:<bean abstract="true" />
employee.group=Insurance // 为属性设置值,等同于:<property name="group" value="Insurance" />
employee.usesDialUp=false // 为employee这个bean中的usesDialUp属性设置值,等同于:等同于:<property name="usesDialUp" value="false" />
1.1.4. 注解方式
使用 @Compontent 注解来定义一个bean,配置类中使用 @Bean 注解来定义bean
1.2. 总结
Bean注册者只识别 BeanDefinition 对象,不管什么方式最后都会将这些bean定义的信息转换为BeanDefinition对象,然后注册到Spring容器中
2. Bean元信息解析阶段
Bean元信息的解析就是将各种方式定义的bean配置信息解析为BeanDefinition对象。
3. 将Bean注册到容器中
通过 BeanDefinitionRegistry接口将 Bean注册、获取、移除等操作
4. BeanDefinition合并阶段
我们定义bean的时候有父子bean关系,此时子BeanDefinition中的信息是不完整的,比如设置属性的时候配置在父BeanDefinition中,此时子BeanDefinition中是没有这些信息的,需要将子bean的BeanDefinition和父bean的BeanDefinition进行合并,得到最终的一个RootBeanDefinition
,合并之后得到的RootBeanDefinition
包含bean定义的所有信息,包含了从父bean中继继承过来的所有信息,后续bean的所有创建工作就是依靠合并之后BeanDefinition来进行的。
5. Bean Class加载阶段
这个阶段就是将bean的class名称转换为Class类型的对象。BeanDefinition中有个Object类型的字段 beanClass,用来表示bean的class对象,通常这个字段的值有2种类型,一种是bean对应的Class类型的对象,另一种是bean对应的Class的完整类名,第一种情况不需要解析,第二种情况:即这个字段是bean的类名的时候,就需要通过类加载器将其转换为一个Class对象。此时会对阶段4中合并产生的RootBeanDefinition
中的beanClass
进行解析,将bean的类名转换为Class对象
,然后赋值给beanClass
字段。
6. Bean实例化阶段
这个过程会通过反射来调用bean的构造器来创建bean的实例。具体需要使用哪个构造器,Spring为开发者提供了一个接口,允许开发者自己来判断用哪个构造器。
7. 合并后的BeanDefinition处理
8. 属性赋值阶段(3个小阶段)
- 实例化后阶段,2. Bean属性赋值前处理 ,3. Bean属性赋值
9. Bean初始化阶段(5个小阶段)
-
Bean Aware接口回调
-
Bean初始化前操作
-
Bean初始化操作
-
Bean初始化后操作
-
Bean初始化完成操作
10. 所有单例bean初始化完成后阶段
所有单例bean实例化完成之后,spring会回调下面这个接口:
java
public interface SmartInitializingSingleton {
void afterSingletonsInstantiated();
}
11. Bean使用阶段
调用getBean方法得到了bean之后
12. Bean销毁前阶段
触发bean销毁的几种方式
-
调用org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#destroyBean
-
调用org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons
-
调用ApplicationContext中的close方法
原文详情地址https://blog.csdn.net/qq_38361800/article/details/106418195
七. Spring循环依赖解决
第⼀级缓存: singletonObjects,⽤于保存实例化、注⼊、初始化完成的 bean 实例;
第⼆级缓存: earlySingletonObjects,⽤于保存实例化完成的 bean 实例;
**第三级缓存:**singletonFactories,用于保存 bean 创建⼯⼚,以便后面有机会创建代理对象。执⾏逻辑:
1.先从一级缓存中找,找不到后去二级缓存找,还没有就去三级缓存找
- ⼀级缓存作⽤: 变量命名为 singletonObjects,结构是 Map,它就是⼀个单例池, 将初始化好的对象放到⾥⾯,给其它线程使⽤,如果没有第⼀级缓存,程序不能保证 Spring 的单例属性。
- 三级缓存作⽤: 变量命名为 singletonFactories,结构是 Map>,Map 的 Value 是⼀个对象的代理⼯⼚,所以"三级缓存"的作⽤,其实就是⽤来存放对象的代 理⼯⼚。
- **⼆级缓存作⽤:**主要是⽤来存放对象⼯⼚⽣成的对象,这个对象可能是原对象,也可能是个代理对 象。