在 Spring Bean 描述了一个 bean 的生命周期,那么这些生命周期中的方法是什么时候执行调用的呢?
refresh() 方法在 ConfigurableApplicationContext 接口中定义,而具体的实现是在 AbstractApplicationContext 中。
refresh() 方法是一个启动方法,调用该方法后,会实例化所有单例以及非单例的对象。
而通过 refresh() ,可以学习到 Spring 是如何初始化 bean 的,分析过程如下:
我们先来看看 refresh() :
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
//刷新加载之前的上下文
this.prepareRefresh();
//告诉子类刷新内部bean工厂
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//准备在上下文中使用的 bean 工厂
this.prepareBeanFactory(beanFactory);
try {
//允许上下文的子类去执行postProcessor
this.postProcessBeanFactory(beanFactory);
// 开始执行注册到该上下文的BeanFactoryPostProcessors
this.invokeBeanFactoryPostProcessors(beanFactory);
// 开始注册BeanPostProcessor来拦截其他的bean的初始化过程
this.registerBeanPostProcessors(beanFactory);
//初始化上下文的消息源
this.initMessageSource();
//初始化上下文的事件传播器
this.initApplicationEventMulticaster();
//在特定上下文子类中初始化其他特殊bean
this.onRefresh();
//检查监听器bean并注册
this.registerListeners();
//实例化所有剩余的单例
this.finishBeanFactoryInitialization(beanFactory);
//发布相应的事件
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
obtainFreshBeanFactory 方法会实例化 BeanFactory 并加载解析对应的 Bean :
初始化 BeanFactory
protected final void refreshBeanFactory() throws BeansException {
//如果已经有了一个容器,先销毁里面的bean然后再关闭容器,spring保证只有一个容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建BeanFactory实例
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
//加载bean
loadBeanDefinitions(beanFactory);
//为DefaultListableBeanFactory beanFactory赋值
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
是 refreshBeanFactory 中的,用于加载bean
创建一一个XmlBeanDefinitionReader,然后调用 loadBeanDefinitions:
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
String[] configLocations = getConfigLocations();//获取我们的 bean.xml 文件
if (configLocations != null) {
for (String configLocation : configLocations) {
//通过XmlBeanDefinitionReader解析我们的xml文件,初始化BeanDefinition
reader.loadBeanDefinitions(configLocation);
}
}
}
而初始化后的BeanDefinition放在哪呢?
XmlBeanDefinitionReader 中我们还传入了 beanFactory,看下生成的BeanFactory下的属性:
reader.loadBeanDefinitions(configLocation) 会将解析出来的每个 bean 注册(put)到 beanFactory 中的 beanDefinitionMap 中,registry就是我们存入 beanFactory,而 registerBeanDefinition 方法内部就是调用 map 的 put 方法。
就是获取 refreshBeanFactory 方法所创建的 BeanFactory
先介绍一下有关的四个接口:
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
BeanFactoryPostProcessor 区别于 beanPostProcesso 修改的是当我们初始化Bean的时候,“临时”修改bean的属性,而 beanFactoryPostProcessor 修改的是BeanDefinnition。
BeanNameAware 实现该接口的bean会意识到自己在beanfactory的的名字
BeanFactoryAware 可以在实现BeanFactoryAware的bean中获取beanfactory,也就是获取上下文
该方法会先在 BeanDefinition 获取到实现了 BeanFactoryPostProcessor 这个接口的bean的名称:
这些名称会根据是否实现 Order 等接口分类:
然后根据 bean 的名称获取到相应的 BeanFactoryPostProcessor ,比如:
由上面可知,getBean 方法用于初始化实现BeanFactoryPostProcessor这个接口的bean,实例化好了之后放入List
if (!typeCheckOnly) {
markBeanAsCreated(beanName);//标记当前bean正在创建
}
try {
//获取这个bean的beanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();//获取这个bean依赖的bean
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
if (isDependent(beanName, dependsOnBean)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
}
registerDependentBean(dependsOnBean, beanName);
//创建依赖的 bean,从这可以看出所有 bean 的创建都和 getBean 这个核心方法有关
getBean(dependsOnBean);
}
}
if (mbd.isSingleton()) {//单例的情况
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
//五种域的情况都得调用这个 createBean 方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
//确保该 bean 的 class 真实存在
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
//准备方法的重写
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 返回 beanPostProcessor 修改后的bean
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
//正常创建一个 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
初始化一个 BeanWrapper
进入createBeanInstance 的 instantiateBean 方法:通过反射使用默认构造器实例化该 bean,此时还没有 setter 赋值。
回到 doCreateBean : 前面实例化后,这里会开始初始化
进入 initializeBean 方法: 开始执行 aware 相关方法(BeanFactoryAware 和 BeanNameAware)
进入invokeInitMethods方法: 先判断该 bean 是否实现了 InitializingBean,如果有则执行 afterPropertiesSet,然后再执行 init-method
前面我们所说的是实现了 BeanFactoryPostProcessor 接口的bean的初始化过程,那实现了 BeanPostProcessor 接口的bean的初始化呢?是是通过如下的方法:
其实 finishBeanFactoryInitialization 方法初始化的过程和上面是一样的,都是通过 getBean 方法:
而在执行 invokeInitMethods 的前后就有对 BeanPostProcessor 接口中方法的调用: