IoC(Inverse of Control:控制反转)是一种设计思想,就是 将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语言中也有应用,并非 Spirng 特有。 IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象
使用 ApplicationContext,它是 BeanFactory 的子类,更好的补充并实现了 BeanFactory ,BeanFactory可以理解为一个HashMap,key:bean name value:bean object,它只有get put两个功能,所以被称为低级容器,ApplicationContext 继承了多个接口,所以称为高级容器,可以从classpath 和 fileSystem 加载配置文件
何为控制,控制的是什么?
- 是bean的创建、管理的权利,控制bean的整个生命周期
何为反转,反转了什么?
- 把这个权利交给了 Spring 容器,而不是自己去控制,就是反转
何为依赖,依赖的是什么?
- 程序运行需要依赖外部的资源,提供程序内对象的所需要的数据、资源
何为注入,注入了什么?
- 配置文件把资源从外部注入到内部,容器加载了外部的文件、对象、数据,然后把这些资源注入给程序内的对象,维护了程序内外对象之间的依赖关系
- 对象在容器中默认是单例的
- 容器中的对象是启动容器的时候,就已经创建好了所有的对象,使用反射clazz.getDeclaredConstructor().newInstance() 创建
依赖注入的方式
- 手动注入
- xml、注解配置元信息
- 自动注入
- Autowiring
依赖注入的类型
- setter注入:<property>
- 构造器注入:<construct-arg>
- 接口注入:实现ApplicationContextAware接口
- 方法注入:@Autowired @Bean @Resource
自动装配模式
- no:(默认)无自动装配。Bean 引用必须由ref元素定义。对于大型部署,建议不要更改默认设置,因为明确指定协作者可以提供更好的控制和清晰度。在某种程度上,它记录了系统的结构
- byName:按属性名称自动布线。Spring 寻找与需要自动装配的属性同名的 bean。例如,如果一个 bean 定义被设置为按名称自动装配,并且包含一个master属性(即,它具有setMaster(..)方法),那么 Spring 将查找一个名为master的 bean 定义并使用它来设置属性
- byType:如果容器中恰好存在一个该属性类型的 bean,则使该属性自动装配。如果存在多个错误,则会引发致命异常,这表明您可能不对该 bean 使用byType自动装配。如果没有匹配的 bean,则什么也不会发生(未设置该属性)
- constructor:类似于byType,但适用于构造函数参数。如果容器中不存在构造函数参数类型的一个 bean,则将引发致命错误
Spring 中的 bean 的作用域有哪些?
- singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
- prototype : 每次请求都会创建一个新的 bean 实例。
- request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
- session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。
- global-session: 全局 session 作用域,仅仅在基于 Portlet 的 web 应用中才有意义,Spring5 已经没有了。Portlet 是能够生成语义代码(例如:HTML)片段的小型 Java Web 插件。它们基于 portlet 容器,可以像 servlet 一样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。
Spring bean 的生命周期
对于 Spring Bean 的生命周期简单来说来说就包含以下四个步骤:
- 实例化 Instantiation
- 属性赋值 Populate
- 初始化 Initialization
- 销毁 Destruction
Spring Bean 生命周期流程图
看到一个拟人化的流程讲解,感觉很形象,来自后面参考的一篇博文
构造器注入和 Setter 注入有啥区别?更推荐什么方式?
- 在Setter注入,可以将依赖项部分注入,构造方法注入不能部分注入
- 使用setter注入不能保证类的所有的属性都注入进来
- 在类对象相互依赖的时候可以通过Setter方式解决循环依赖问题
怎么解决多个类型相同的bean注册到Spring容器的使用问题?
- @Qualifier注解来指定哪一个bean或者实现bean的逻辑分组
Spring 容器工厂分为两种:ApplicationContext、BeanFactory。异同点:
- 1. BeanFactory 在启动的时候不会去实例化 Bean,ApplicationContext 在启动的时候会。
- 2. BeanFacotry 是 spring 中比较原始的 Factory,无法支持 spring 的许多插件,如 AOP 功能、Web 应用等。 ApplicationContext 支持
IOC的优缺点
- 优点:
- 对于单例的对象,不浪费空间
- 降低组件之间的耦合度
- 统一配置,便于管理修改
- 缺点:
- 对象生成使用反射,在效率上有些损耗
Bean的生命周期感兴趣,可以看看AbstractApplicationContext类里的refresh方法,这个方法是AplicationContext容器初始化的关键点。在这个方法里,调用了finishBeanFactoryInitialization方法,这个方法里调用了getBean方法,getBean方法里调用了AbstractBeanFactory的getBean方法,最终经过一阵七拐八绕,到达了我们的目标——Bean创建的方法:doCreateBean方法,在这个方法里可以看到Bean的实例化,赋值、初始化的过程,至于最终的销毁,可以看看ConfigurableApplicationContext#close()
看到两个讲的特别好的文档,共勉,里面也有调用实现case,这里不做重复赘述
一文读懂 Spring Bean 的生命周期
Spring Bean生命周期,好像人的一生