主要讲解 Spring 生命周期中实例化后的方法。方法入口为 populateBean(beanName, mbd, instanceWrapper),该方法除了调用 InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation 方法(实例化后的扩展接口),还会进行属性的依赖注入,即给 Bean 中符合要求的字段进行属性填充。
Spring 容器初始化的过程主要是在 IoC 容器中建立 BeanDefinition 数据,在此过程中没有涉及到对 Bean 依赖关系进行注入。
假设 IoC 容器已经载入了用户定义的 Bean 信息。注入到依赖注入的过程是“用户第一次向 IoC 容器索要 Bean 时”,触发索要 Bean 的相关属性和方法的依赖注入。当然也有例外,也就是我们可以在 BeanDefinition 信息中通过控制 azy-init 属性来让容器完成对 Bean 的预实例化。预实例化实际上也是一个完成依赖注入的过程,但是它是在初始化的过程中完成的。
1.依赖注入流程图
上面说了,依赖注入的过程是“用户第一次向 IoC 容器索要 Bean 时触发的”,那是向谁索要?如何索要的呢?
其实,谁保存了 Bean 信息就是向谁索要。也就是向 BeanFactory 索要,索要的方法就是 BeanFactory 定义的 getBean 方法。调用这个接口,就等于触发依赖注入了。
首先介绍 getBean 的大致过程,
(1)如果缓存中能取得我们想要的Bean,取得那些已经被创建过的Singleton的Bean,对这种Bean的请求不需要重复创建;
(2)如果缓存中不能取得的话,并且有parentBeanFactory的话,就利用 getBean() 方法从parentBeanFactory中取;
(3)如果parentBeanFactory中也取不到的话,那就根据Bean的类型(Singlton或Prototype或其它)去创建我们Bean(createBean方法)。
创建 Bean,是在 createBean 方法中进行的,本文要介绍的依赖注入也是在这里进行的。这个方法是在 AbstractAutowireCapableBeanFactory 类中,下面介绍 createBean 方法,源码如下
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
// 这里判断需要创建的Bean是否可以实例化,这个类是否可以通过类装载器来载入
// Make sure bean class is actually resolved at this point.
resolveBeanClass(mbd, beanName);
// Prepare method overrides.
try {
mbd.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 如果配置了PostProcessor,那么这里返回的是一具proxy。
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbd);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 调用真正创建Bean的方法
Object beanInstance = doCreateBean(beanName, mbd, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
看完了上面的代码,我们发现在 createBean 方法里做下面几件事:
(1)创建 Bean 之前,先判断需要创建的 Bean 是否可以实例化,这个类是否可以通过类装载器来载入;
(2)如果配置了 PostProcessor,那么这里返回的是一具 proxy;
(3)如果没有配置 PostProcessor,就调用子方法创建 Bean。
即,这里的主要工作是进行“Bean是否可以实例化、这个类是否可以通过类装载器来载入”的判断,以及“是否配置 PostProcessor 的检查”。如果都没什么问题,再继续创建 Bean。继续创建 Bean 的方法是 doCreateBean 方法。