1.IOC思想概述
所谓的IOC(inversion of control),就是控制反转的意思。
原来这个对象的控制权在我们的代码中,我们自己new的对象,在Spring中,应用程序不再控制对象的创建,而是被动地接受由容器注入的对象。
控制权被转移到Spring容器中,容器负责创建和管理对象,并在需要的时候将它们注入到应用程序中。
2.继承关系
这边主要介绍BeanFactory和ApplicationContext
- ApplicationContext是BeanFactory的子类,并且与beanFactory是组合的关系。并且每次getBean()底层都是依赖BeanFactory来进行依赖查找
- BeanFactory是IOC的底层,提供了最基本的方法。而ApplicationContext是beanFactory的派生,提供了许多beanFactory所不能完成的功能,同时也拥有BeanFactory的所有功能,是对BeanFactory的扩展
- 在实际使用中也更多的是使用ApplicationContext来获取对象,判断是否单例等
3.SpringBoot对Bean的管理
Bean的Spring容器加载
Bean的来源一共就两种方式:
- 第三方bean:SpringBoot的自动配置
- 本地bean:使用@Conponent
自动配置
由于使用了EnableAutoConfiguration注解,该注解Import的EnableAutoConfigurationImportSelector会去扫描classpath下的所有spring.factories文件,自动的给你生成一些Bean,并加载到Spring的Context中。
@Conponent
由自己添加注解,将该类交由Spring容器管理
Spring Bean生命周期
整个生命周期可以大致分为3个大的阶段,分别是:创建、使用、销毁。还可以进一步分为5个小的阶段:实例化、初始化、注册Destruction回调、Bean的正常使用以及Bean的销毁。
具体到代码方面,可以参考以下这个更加详细的过程介绍,我把具体实现的代码位置列出来了。
实例化Bean:
- Spring容器首先创建Bean实例。
- 在AbstractAutowireCapableBeanFactory类中的createBeanInstance方法中实现
设置属性值:
- Spring容器注入必要的属性到Bean中。
- 在AbstractAutowireCapableBeanFactory的populateBean方法中处理
检查Aware:
- 如果Bean实现了BeanNameAware、BeanClassLoaderAware等这些Aware接口,Spring容器会调用它们。
- 在AbstractAutowireCapableBeanFactory的initializeBean方法中调用
调用BeanPostProcessor的前置处理方法:
- 在Bean初始化之前,允许自定义的BeanPostProcessor对Bean实例进行处理,如修改Bean的状态。BeanPostProcessor的postProcessBeforeInitialization方法会在此时被调用。
- 由AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsBeforeInitialization方法执行。
调用InitializingBean的afterPropertiesSet方法:
- 提供一个机会,在所有Bean属性设置完成后进行初始化操作。如果Bean实现了InitializingBean接口,afterPropertiesSet方法会被调用。
- 在AbstractAutowireCapableBeanFactory的invokeInitMethods方法中调用。
调用自定义init-method方法:
- 提供一种配置方式,在XML配置中指定Bean的初始化方法。如果Bean在配置文件中定义了初始化方法,那么该方法会被调用。
- 在AbstractAutowireCapableBeanFactory的invokeInitMethods方法中调用。
调用BeanPostProcessor的后置处理方法:
- 在Bean初始化之后,再次允许BeanPostProcessor对Bean进行处理。BeanPostProcessor的postProcessAfterInitialization方法会在此时被调用。
- 由AbstractAutowireCapableBeanFactory的applyBeanPostProcessorsAfterInitialization方法执行
注册Destruction回调:
- 如果Bean实现了DisposableBean接口或在Bean定义中指定了自定义的销毁方法,Spring容器会为这些Bean注册一个销毁回调,确保在容器关闭时能够正确地清理资源。在AbstractAutowireCapableBeanFactory类中的registerDisposableBeanIfNecessary方法中实现
Bean准备就绪:
- 此时,Bean已完全初始化,可以开始处理应用程序的请求了。
调用DisposableBean的destroy方法:
- 当容器关闭时,如果Bean实现了DisposableBean接口,destroy方法会被调用。
- 在DisposableBeanAdapter的destroy方法中实现
调用自定义的destory-method:
- 如果Bean在配置文件中定义了销毁方法,那么该方法会被调用。
- 在DisposableBeanAdapter的destroy方法中实现
初始化阶段对Bean处理
这里主要列举可以实现哪些功能
- 缓存预热
- Bean的优先加载
Bean的实例化时机
对于Prototype:
- 在第一次请求的时候才被实例化的
对于Singleton:
- 一般在IoC容器启动的时候就被实例化,然后被缓存在内存中
- 如果bean标签中有设置lazy-init=true,则会在第一次请求时才会被实例化,而不是在容器启动的时候就被实例化
- 但是,当一个懒实例化的Bean依赖了一个非懒实例化的Bean,那么IOC容器在启动的时候也会实例化这个Bean,因为它必须满足单例的依赖性
在默认情况下:
spring容器会在启动时就创建并初始化所有的单例Bean(@Conponent注解的默认作用域是单例)
Bean的自动注入
@Autowired(Spring自带)
Autowired在获取bean的时候,先是byType的方式,再是byName的方式。意思就是先在Spring容器中找以Bean为类型的Bean实例,如果找不到或者找到多个bean,则会通过fieldName来找.
@Resource(JDK自带)
Resource在获取bean的时候,和Autowired恰好相反,先是byName方式,然后再是byType方式。当然,我们也可以通过注解中的参数显示指定通过哪种方式。
作用域不同
- Autowired可以作用在构造器,字段,setter方法上
- Resource 只可以使用在field,setter方法上
4.Bean自动注入所存在的问题
这边只做简单介绍,不理解的部分欢迎留言。
循环依赖
- 在Spring框架中,循环依赖是指两个或多个bean之间相互依赖,形成了一个循环引用的情况。如果不加以处理,这种情况会导致应用程序启动失败。
- 在Spring中,解决循环依赖的方式就是引入了三级缓存。
三层缓存所存在的问题
Spring解决循环依赖是有一定限制的:
- 首先就是要求互相依赖的Bean必须要是单例的
- 另外就是依赖注入的方式不能都是构造函数注入的方式
@Lazy
- 用来解决构造器注入这种方式下的循环依赖。
思考
- 为什么只支持单例
- 为什么三层缓存不能解决构造器注入
- 构造器注入和字段注入有啥区别
欢迎评论区留言交流!共同进步!