Spring框架
我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。
比如说 Spring 支持 IoC(Inversion of Control:控制反转) 和 AOP(Aspect-Oriented Programming:面向切面编程)、可以很方便地对数据库进行访问、可以很方便地集成第三方组件(电子邮件,任务,调度,缓存等等)、对单元测试支持比较好、支持 RESTful Java 应用程序的开发。
Spring框架的核心模块

Core Container
Spring框架的核心模块,主要提供IoC依赖注入功能的支持。Spring其他所有的功能都依赖该模块
-
spring-core:Spring框架的核心工具类
-
spring-beans:提供对bean的创建、配置和管理等都功能的支持
-
spring-context:提供对国际化、事件传播、资源加载等功能的支持
-
spring-expression:提供对表达式语言的支持,只依赖于core模块,可以单独使用。
AoP
-
spring-aspects:该模块为于AspectJ的集成提供支持。
-
spring-apo:提供了面向切面的编程实现。
-
spring-instrument:提供了为JVM添加代理的功能。使用场景非常有限。
Data Access/Integration
-
spring-jdbc:提供了对数据库访问的抽象JDBC。不同的数据库都有自己独立的API用于操作数据库,Java程序只需要和API交互,屏蔽了数据库的影响。
-
spring-tx:提供对事物的支持
-
spring-orm:提供对Hibernate、JPA、iBatis等ORM框架的支持。
-
spring-oxm:
-
spring-jsm:消息服务。
Spring Web
-
spring-web:对 Web 功能的实现提供一些最基础的支持。
-
spring-webmvc:提供对 Spring MVC 的实现。主要赋予 Spring 快速构建 MVC 架构的 Web 程序的能力。MVC 是模型(Model)、视图(View)、控制器(Controller)的简写,其核心思想是通过将业务逻辑、数据、显示分离来组织代码。
-
spring-websocket:提供了对 WebSocket 的支持,WebSocket 可以让客户端和服务端进行双向通信。
-
spring-webflux:提供对 WebFlux 的支持。WebFlux 是 Spring Framework 5.0 中引入的新的响应式框架。与 Spring MVC 不同,它不需要 Servlet API,是完全异步。
IOC思想
Spring IOC(Inversion of Control:控制反转)的思想是将创建对象的控制权交由Spring框架来管理。之前都是通过new的方式手动创建对象,在使用Spring框架之后,可以通过XML配置好需要的对象或者在SpringBoot中通过注解的方式配置,使用的时候直接引用就好了。
在 Spring 中, IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。
DI(依赖注入)
依赖注入(DI) 是IOC思想的一种实现方式。Spring容器也是通过这种形式管理Bean的。比如:A类要依赖B类,A类不再直接创建B类的实例,而是把这种依赖关系配置在外部xml文件或者通过注解配置依赖关系,然后由Spring容器根据配置信息创建、管理bean类。
BeanFactory和ApplicationContext
BeanFactory和ApplicationContext是Spring的两大核心接口,ApplicationContext是BeanFactory的子接口。
bean什么时候被实例化
-
如果使用BeanFactory作为Spring Bean的工厂类,则所有的Bean都是在第一次使用该Bean(调用getBean)的时候实例化。
- 这种方式无法发现一些Spring的配置问题。如果bean的某一个属性没有注入,BeanFactory加载后,直至第一次调用getBean方法才会抛出异常。
-
如果使用ApplicationFactory作为工厂类,则分为以下情况:
-
如果bean是singleton的,并且lazy-init为false,则ApplicationContext启动的时候就实例化该Bean,并且将实例化的bean放在一个map结构的缓存中,下次再用的时候直接从缓存中获取。
-
如果scope是singleton,且lazy-init为true或者使用@Lazy注解将其设置为懒加载模式,则:容器在解析注册Bean定义时进行预实例化??
-
如果scope是prototype,则在第一次使用该bean的时候实例化。
-
Bean的作用域有哪些
-
singleton:单例,Ioc容器中只有唯一的bean实例。
-
prototype:每次获取都会创建一个新的bean实例。也就是说,连续getBean()两次,得到的是不同的实例。
-
request:仅web应用可用。每次http请求都会产生一个新的bean,且仅在当前http request内生效
-
session:仅web应用可用。每次来自新session的http请求都会产生一个新的bean,仅在当前http session内有效。
-
application/gloable-session:仅web应用可用。每个web应用在启动时创建一个bean,仅在启动时间。
-
websocket:每次websocket回话产生一个新的bean。
如何配置bean的作用域
xml方式
xml
<bean id = "..." class="..." scope="singleton"></bean>
注解方式:
java
@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Persion personPrototype(){
return new Person();
}
Bean是否线程安全
Spring 框架中的 Bean 是否线程安全,取决于其作用域和状态。
最常用的两种作用域 是prototype 和 singleton 。几乎所有场景的 Bean 作用域都是使用默认的 singleton ,重点关注 singleton 作用域即可。
- prototype 作用域下,每次获取都会创建一个新的 bean 实例,不存在资源竞争问题,所以不存在线程安全问题。
- singleton 作用域下,IoC 容器中只有唯一的 bean 实例,可能会存在资源竞争问题(取决于 Bean 是否有状态)。
- 如果这个 bean 是有状态的话,那就存在线程安全问题(有状态 Bean 是指包含可变的成员变量的对象)
- 不过,大部分 Bean 实际都是无状态(没有定义可变的成员变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。
对于有状态单例 Bean 的线程安全问题,常见的有两种解决办法:
- 在 Bean 中尽量避免定义可变的成员变量。
- 在类中定义一个
ThreadLocal
成员变量,将需要的可变成员变量保存在ThreadLocal
中(推荐的一种方式)。
Bean的生命周期

这个部分还需要再详细学习一下。