1. Spring IoC 容器初始化主题流程
1.1 Spring IoC容器体系
- 容器是一组组件和过程的合集,包括BeanFactory、单例池、BeanPostProcessor等
用于存放和管理实例化对象的
**Map**
集合其实是容器中的单例池BeanFactory
BeanFactory注释第一句话:
_The root interface for accessing a Spring bean container._
获取Bean对象
Object getBean
- 获取Bean的提供者
<T> ObjectProvider<T> getBeanProvider
- 判断Factory是否有Bean
boolean containsBean
- 判断是否为单例Bean
boolean isSingleton
- 判断是否为原型Bean
boolean isPrototype
- 判断是否匹配类型
boolean isTypeMatch
- 获取Bean类型
Class<?> getType
- 获取别名
String[] getAliases
- FactoryBean 定位符:
String _FACTORY_BEAN_PREFIX _= "&";
- Spring的Bean分两种:普通Bean和FactoryBean,Spring会通过
"&"
来定位区分FactoryBean1.2 Bean 生命周期关键时间点
| 关键点 | 触发代码 | | —- | —- | | 构造器执行、初始化方法调用 | refresh#finishBeanFactoryInitialization(beanFactory) | | BeanFactoryPostProcessor 初始化 | refresh#invokeBeanFactoryPostProcessors(beanFactory) | | BeanFactoryPostProcessor ⽅法调⽤ | refresh#invokeBeanFactoryPostProcessors(beanFactory) | | BeanPostProcessor 初始化 | refresh#registerBeanPostProcessors(beanFactory) | | BeanPostProcessor ⽅法调⽤ | refresh#finishBeanFactoryInitialization(beanFactory) |
- Spring的Bean分两种:普通Bean和FactoryBean,Spring会通过
SpringBean的生命周期
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
- 如果涉及到一些属性值 利用
set()
方法设置一些属性值。 - 如果 Bean 实现了 BeanNameAware 接口,调用
setBeanName()
方法,传入 Bean 的名字。 - 如果 Bean 实现了 BeanClassLoaderAware 接口,调用
setBeanClassLoader()
方法,传入 ClassLoader对象的实例。 - 如果 Bean 实现了 BeanFactoryAware 接口,调用
setBeanFactory()
方法,传入 BeanFactory对象的实例。 - 与上面的类似,如果实现了其他 .*Aware接口,就调用相应的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行
postProcessBeforeInitialization()
方法 - 如果 Bean 实现了InitializingBean接口,执行
afterPropertiesSet()
方法。 - 如果 Bean 在配置文件中的定义包含
_ init-method_
属性,执行指定的方法。 - 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行
postProcessAfterInitialization()
方法 - 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行
destroy()
方法。 - 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含
destroy-method
属性,执行指定的方法。
1.3 容器初始化主流程
refersh() 方法
/**
* Load or refresh the persistent representation of the configuration, which
* might be from Java-based configuration, an XML file, a properties file, a
* relational database schema, or some other format.
* <p>As this is a startup method, it should destroy already created singletons
* if it fails, to avoid dangling resources. In other words, after invocation
* of this method, either all or no singletons at all should be instantiated.
* @throws BeansException if the bean factory could not be initialized
* @throws IllegalStateException if already initialized and multiple refresh
* attempts are not supported
*/
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
/*
* 刷新前的预处理
* 设置spring容器的启动时间
* 开启活跃状态,撤销关闭时间
* 验证环境信息里一些必须属性
*/
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/*
* 获取BeanFactory; 默认实现是DefaultListableBeanFactory
* 加载BeanDefinition并注册到BeanDefinitionRegistry
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
/*
* BeanFactory的准备工作,比如context的类加载器等
*/
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 实例化实现了BeanFactoryPostProcessor接口的Bean,并调用接口方法
/*
* 在此之前,所有bean definition都已加载,但还没有实例化任何bean。
* BeanFactoryPostProcessor是针对BeanFactory的扩展,
* 主要用在bean实例化之前,读取bean的定义,并可以修改它。
*/
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册Bean的后置处理器
// 本方法会注册所有的 BeanPostProcessor,将所有实现了 BeanPostProcessor 接口的类加载到 BeanFactory 中。
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
/*
* 初始化所有剩下的非懒加载的单例Bean
* 创建非懒加载方式的单例Bean
* 设置Bean的属性
* 初始化方法调用
* 调动BeanPostProcessor对实例Bean进行后置处理
*/
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
获取BeanFactory与加载BeanDefinitions
**ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();**
**obtainFreshBeanFactory()**
:
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
BeanDefinition
什么是BeanDefinition
- BeanDefinition描述一个bean实例,该实例具有属性值、构造函数参数值和由具体实现提供的进一步信息。
- BeanDefinition里存着bean的属性值,构造函数等等的信息。
- 其实就是将xml里的bean属性,存到了BeanDefinition的某些属性里面,用的时候,从BeanDefinition的这些属性里取值。
- 另外我们可以通过BeanFactoryPostProcessor来修改加载到BeanDefinition对象中的bean的属性。
BeanDefinition设置过程的调用链
Bean对象的创建流程
**beanFactory.preInstantiateSingletons();**
- 先处理FactoryBean
- 然后创建普通Bean,走
getBean()
方法 doGetBean()
方法- 做一些基础设置
- 以创建单例Bean为例:
Bean初始化的主体类
spring bean 的流程全在 AbstractAutowireCapableBeanFactory 类中实现
- 在第5步的
createBean
,调用AbstractAutowireCapableBeanFactory实现的createBean
方法
doCreateBean(beanName, mbdToUse, args);
中的流程即是SpringBean的生命周期- 通过反射创建单例Bean:
instanceWrapper = createBeanInstance(beanName, mbd, args);
- 设置Bean的属性:
populateBean(beanName, mbd, instanceWrapper);
- 在
initializeBean(beanName, exposedObject, mbd);
方法中:- 检查Aware借口并设置相关依赖
- 通过反射创建单例Bean:
2. **设置BeanPostProcessors 前置处理器**
3. **初始化方法**
4. **BeanPostProcessors 后置处理器**
延迟加载
循环依赖
无法解决
- 原型Bean的循环依赖无法解决
- 单例Bean构造器参数循环依赖无法解决
可以解决
- 单例Bean通过set方法或者
@Autowired
注入依赖
循环依赖解决原理
假设Class A 和Class B 相互依赖
- 初始化A的过程中,先通过构造器生成A的实例,把他提前暴露到spring容器中(
singletonFactories
三级缓存);(生命周期种的7.a)
- 给A设置属性
populateBean(beanName, mbd, instanceWrapper);
(生命周期种的7.b) - 发现A依赖于B;
populateBean
—>applyPropertyValues(beanName, mbd, bw, pvs)
AbstractBeanFactory - 开始创建B,设置属性之前 同创建A的流程一样;(这里就又回生命周期的2)
- 设置属性时发现依赖于A,同样和3的流程一样,直到走到AbstractBeanFactory的
doGetBean
方法。
doGetBean
方法中的getSingleton
从缓存中获取A
- 首先从一级缓存(
singletonObjects
)中获取,如果没有,然后二级缓存(earlySingletonObjects
),然后三级缓存(singletonFactories
),从三级缓存中拿到A的幼年期对象,然后加入了二级缓存;并从三级缓存中删除。
- 返回A的 幼年期(未创建完全)对象
- 创建B完成,加入一级缓存
- A从一级缓存中,获取B的依赖
2. Spring AOP
首先,springAOP是通过生成类的代理对象,进行方法增强,
所以,这时候正好就用到了beanPostProcesser