spring ioc 即控制反转,就是将我们创建和管理对象交给了spring进行处理; 我们只需要通过配置文件描述对象, 容器加载配置文件描述,并将其转换为Bean Difinition , 然后通过BeanFactory 来生产对象,当然单利在创建一次后会缓存在bean容器中。
Spring IOC 主要实现依赖于 工厂模式 + 反射;
BeanFactory - BeanFactory 就像一个包含 bean 集合的工厂类。它会在客户端要求时实例化 bean。 ApplicationContext - ApplicationContext 接口扩展了 BeanFactory 接口。它在 BeanFactory 基础上提供了一些额外的功能。
定义bean可以通过xml <bean> 标签的形式进行配置;其次现在使用注解形式进行配置;
加载过程是:
image.png
spring 将配置解析为bean定义:
class: 类路径名
scope: 单利,原型
autowaremode: 注入模型
lazyInit 是否是懒加载
默认注入模型是 0, 在使用的时候必须加@Autoware
可以在后置处理器修改注入模型,1,2 分别是byName, byType, 在类中必须写setXXX方法 它就会自动的注入进去;
懒加载,依赖,构造参数等记录;
spring 提供一个扩展机会再bean definition 还没进行实例化的时候,还可以对其进行扩展。 修改我们bean definition 的属性;
BeanFactoryPostProcessor 修改的是我们的bean定义,相当于修改的是类型,而不是具体的实例;
BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子类,在父类的基础上,增加了新的方法,允许我们获取到BeanDefinitionRegistry,从而编码动态修改BeanDefinition。例如往BeanDefinition中添加一个新的BeanDefinition。
BeanDefinitionRegistryPostProcessor,这也就是我们在@import中实现第二种方法的原理;
也就是在getBean 之前进行调用;
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//bean初始化方法调用后被调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
BeanPostProcessor 是在我们bean进行初始化前后进行工作;
它是在getBean()后对bean进行初始化前后进行调用;
spring 容器启动流程:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 刷新前准备工作
prepareRefresh();
// 调用子类refreshBeanFactory()方法,获取bean factory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 创建bean Factory的通用设置
prepareBeanFactory(beanFactory);
try {
// 子类特殊的bean factory设置
postProcessBeanFactory(beanFactory);
// 实例化beanFactoryPostProcessor
// 调用beanFactoryPostProcessor修改bean definition
invokeBeanFactoryPostProcessors(beanFactory);
// 注册 bean pst processors
registerBeanPostProcessors(beanFactory);
// 初始化信息源,和国际化相关
initMessageSource();
// 初始化容器事件传播器
initApplicationEventMulticaster();
// 调用子类特殊的刷新逻辑
onRefresh();
// 为事件传播器注册事件监听器
registerListeners();
// 实例化所有非懒加载单例
finishBeanFactoryInitialization(beanFactory);
// 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
// ...
}
finally {
// ...
}
}
}
bean 的生命周期指的是getBean后的生命周期;
spring bean 容器的生命周期流程如下:
DI大概是这样的,根据我们要获取的BeanName,去IOC容器中找到对应的class,然后实例化出一个代理类对象,然后给这个对象的属性赋值。
3.1 判断是不是原型实例,如果是,则抛出创建失败异常,如果不是,下一步。
3.2 检查 BeanDefinition 是否在当前的容器中,如果不在那可能在父类容器中,所以委托父类容器查找,如果还没有,则再上一级容器...递归查找。
3.3 检查这个实例是否是为了类型检查而获取,而不是用来使用,如果是,标记这个bean已经被创建,如果不是,下一步。
3.4 根据 beanName获取 父类的BeanDefinition,并检查该对象类类型,比如不能是抽象类等。
3.5 根据 beanName获取所有该 bean依赖的 Bean集合,如果该集合有值,则遍历DI(递归调用 getBean())该 bean集合里的bean,并把bean注册给当前的bean(维护了一个 map来存放关系)。
3.6 如果3.4中获取的 BeanDefinition是单例,则根据该单例对象和 beanName和 args创建一个实例对象;否则,判断 BeanDefinition是否是原型,如果是则根据 beanName,该对象, args创建一个实例;否则拿到3.4获取的 BeanDefinition对象的生命周期 Scope,然后根据 scope来创建实例对象,参数 (beanName,bd,args)。