spring IOC有两个核心思想就是ioc控制反转和DI依赖注入
ioc控制反转的基本思想是,将原先的对象控制从使用者控制,转交给了spring来控制管理
DI注入就是将对应的熟悉值注入到具体的方法之中
spring提供@Autowired和@Resource等注解注入
对象会存储在map中,在spring使用map结构的singletonObjects存放完整的bean对象
整个bean的生命周期从创建到销毁的过程都由sprin来管理
bean的生命周期
bean的生命周期主要分为初始化使用和销毁
1.在正式进入容器的刷新前会有一些前置操作,确定使用的容器,给开发者提供初始化ApplicationContext的机会
2.初始化BeanFactory,加载bean定义
设置一些相关的参数,将beanName,beanDefintion放入bean工厂,用于后续创建bean对象
3.触发BFPP(BeanFactoryPostProcessor)后处理bean的定义。BFPP接口是spring初始化BeanFactory对外暴露的扩展点,Spring IOC允许BFPP在容器实例化任何bean之前读取bean的定义,并可以在此对bean进行进一步处理。BeanDefinitionRegistryPostProcessor继承自BFPP,具有更高的优先级。
我们也可以implements BeanFactoryPostProcessor 在使用@Component注册到spirng,实现自己的postProcessBeanFactory()逻辑
4.查找该bean所需要的依赖,并将其创建(该Bean已经实例化,但未初始化)/注入到该bean对象中
(在这里可以使用@PostConstruct,注入完成之后)
在注入之后,会完善BFPP的执行部分
setBeanName实现,如果这个bena实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值
BeanFactoryAware实现,如果已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory,setBeanFactory(BeanFactory)传递的是spring工厂自身(可以用这个方式获取其他Bean,只需要在Spring配置文件中配置一个普通的Bean就可以)
ApplicationContextAware实现,如果这个bean实现了ApplicationContextAware接口,会调用setApplicationContextAware(ApplicationContext)方法,传入Spring上下文,这个方式同样可以实现BeanFactoryaware的功能。因为ApplicationContext是BeanFactory的子接口,有更多功能
postProcessBeforeInitialization(Object obj,String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用的方法,也可以被应用于内存或缓存技术
init-method, 如果Bean 在Spring 配置文件中配置了init-method 属性会自动调用其配置的初始化方法。
5.触发BPP(BeanPostProcessor):注册所有的BeanPostProcessor,将所有市县BPP的接口的雷加载到BeanFactory中,BPP接口是Spring初始化bena时对外暴露的扩展点,方便后续对bean对象完成具体的扩展功能。将会调用postProcessAfterInitialization(Object obj, String s)方法。
6,生成完整的bean对象,通过getBean的方法可以直接获取使用
注:以上工作完成以后就可以应用这个Bean 了,那这个Bean 是一个Singleton 的,所以一般情况下我们调用同一个id 的Bean 会是在内容地址相同的实例,当然在Spring 配置文件中也可以配置非Singleton。Destroy 过期自动清理阶段
使用
- spring使用反射创造代理对象操作bean
- spirng会通过Proxy,jdk接口,CGLib代理创建代理对象,在对象的基础上使用代理操作对象
- spring boot优先使用CGLib创建代理
销毁
在这里可以使用@PreDesTroy注解(销毁之前)
当Bean 不再需要时,会经过清理阶段,如果Bean 实现了DisposableBean 这个接口,会调用那个其实现的destroy()方法;destroy-method 自配资清理。在BeanFactory关闭的时候,Bean的生命周期会调用以下方法.
- DestructionAwareBeanPostProcessor.postProcessBeforeDestruction(),可以调用自定义回调,像是DisPosaBleBean的销毁和自定义销毁方法,这个回调仅适用于工厂中的单例Bean
- 实现了自定义的destory()方法
Bean的生命周期方法:@PostConstruct和@PreDesTroy
要求:需要是自己编写的类,不是自己的类无法使用注解,只能使用Bean的属性
可以在对象注入之后和销毁之前编写一些代码逻辑,检查内容等
被组件扫描发现后,会自动添加启动和关闭的行为,不可以有返回值与参数
@PostConstruct 所有依赖注入后启动
@PreDesTroy结束时,bean实例销毁之前启动
注意仅当程序是正常关闭时,在会调用preDestroy方法,如果是意外错误,强制中止,不会调用
总结
bean是一个由Spring IOC容器初始化,组装和管理的对象
BeanDefinition是bean的定义,存储bena等等所有方法,属性定义。
ApplicationContext是BeanFactory的子接口,是相对较高级的IOC容器实现。包含BeanFactory的所有功能,还提供了其他的高级特性,比如时间发布,国际化信息支持,统一资源加载策略。
BeanFactory是最基础的IOC容器,提供完整的IOC服务支持
FactoryBean是一种特殊的bena,他是工厂bean,可以自己创建Bean实例
如果一个类实现了FactoryBean接口,该类可以自己定义创建实例对象的方法,只需实现getObjecte()方法即可
IOC的三级缓存是什么![](https://i-blog.csdnimg.cn/blog_migrate/0e3f2c280bbbaa997196e384b7084973.png)
三级缓存(单例工厂)singleFactories :存放ObjectFactory传入时的匿名内部类,返回Bean实例化的Lambda表达式,产生Bean对象
二级缓存二级缓存(早期的单例对象)earlySingletonObjects:存放未被完全创建好的bean对象,判断该对象是否需要被代理
- 不需要,产生bean实例
- 需要,产生代理实例
一级缓存(单利池)singletonObjects:存放完整的bean对象
/**单例对象的缓存:从bean名称到bean实例。 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**早期单例对象的缓存:从bean名称到bean实例。 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/**单例工厂的缓存:对象工厂的bean名称。 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
bean的初始化过程中循环依赖和解决
A类中有一个属性B类,那么spring在创建A对象的时候发现了需要一个B对象,这个时候spring就会暂时停止对A的创建,会先去创建B对象,等B对象创建完之后,将B对象注入到A对象中,再接着创建A对象剩下的工作。
创建bean的过程我们可以分为两部分:
- 通过反射,BFPP定义出一个对象(但是不会初始化),将A对象标为正在创建中,并且放到缓存中。
- 查看它的依赖,再通过BPP往对象中的属性赋值,初始化
第二步中,会先查询是否有依赖需要注入,如果有,spring会先去寻找这个bean对象,有的话直接ID注入,没有则创建中的B对象,将其注入之后再继续创建A对象
在b对象创建时同样会经过这两步,同样在标记b对象正在创建中,存入缓存中后,查找其依赖的A对象,此时发现A对象正在创建中,将这个创建中的A对象为B对象注入,完成B对象的创建
创建好B对象之后,回到A对象,完善A对象的创建
涉及到的模式概念:
享元模式:bean池是一个享元模式
工厂模式:XXXFactory,产生对象的工厂
单例模式:Spring 中 bean 的默认作用域就是 singleton(单例)的。
策略模式:Spring需要针对不同的资源采取不同的访问策略
装饰模式:通过使用修饰模式,可以在运行时扩充一个类的功能。
....