Spring中BeanFactory的创建
在AbstractApplicationContext类的refresh方法是Spring Framework中的关键核心实现,Spring Framework的源码分析主要就是围绕该函数来进行的。在refresh方法中会调用obtainFreshBeanFactory来创建和刷新BeanFactory,本文就来分析一下这个过程。
主refresh方法
首先给出ApplicationContext中的refresh方法代码,本文是在分析该方法中调用的obtainFreshBeanFactory方法,注意和主线结合起来。
java
spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/*
* 通过new DefaultListableBeanFactory()的方式创建容器,
* 这一步会加载bean的定义
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 会注册web作用域
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
/*
* 执行BeanFactoryPostProcessor
*/
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
/*
* 往beanPostProcessors属性中add后置处理器并整理好顺序,便于后续执行
*/
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
/*
* 这一步较简单,向容器里注册一个一个事件源的单例Bean:MessageSource
*/
initMessageSource();
// Initialize event multicaster for this context.
/*
* 初始化Spring的事件多播器:ApplicationEventMulticaster
*/
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
/*
* 模板方法,子类会实现
* 比如在Spring Boot中,会在该方法中创建web服务器
*/
onRefresh();
// Check for listener beans and register them.
/*
* 注册事件监听器
*/
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
/*
* ---- 极其重要步骤 ----
* 会实例化单例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();
contextRefresh.end();
}
}
}
在obtainFreshBeanFactory方法中,主要是调用了两个需要子类实现的模板方法。
java
spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
@Override
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
下面分别来看看这两个模板方法。
refreshBeanFactory方法
该方法主要有两个子类实现了:
- AbstractRefreshableApplicationContext:在传统的Spring + Spring MVC的项目中用的较多,主要包含XmlWebApplicationContext和AnnotationConfigWebApplicationContext,一个基于XML配置,一个基于注解配置。
- GenericApplicationContext:Spring Boot中使用的是这个。
GenericApplicationContext中的实现
java
spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
// CAS设置refreshed为true,表示已刷新
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
// 设置序列化ID
this.beanFactory.setSerializationId(getId());
}
这里好像并没有做什么重要的操作,实际上在构造函数中就已经创建了BeanFactory。
java
spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
AbstractRefreshableApplicationContext中的实现
java
spring-context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) { // 如果已经存在了beanFactory,那么:
destroyBeans(); // 销户所有的bean
closeBeanFactory(); // 关闭beanFactory
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory(); // 注意是DefaultListableBeanFactory,该类是重点
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory); // 把旧容器的一些配置赋值给新容器
/*
* 加载bean配置信息;模板方法,由子类实现
* 在AnnotationConfigWebApplicationContext中(基于注解配置的情况),
* 会创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。
*
* AnnotatedBeanDefinitionReader会注册一些BeanFactoryPostProcessor的BeanDefinition,以便后续使用。
*/
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws BeansException, IOException;
在refreshBeanFactory方法中主要就是做了两件事情。
- 创建BeanFactory;
- 调用loadBeanDefinitions来加载一些bean定义:该方法是个模板方法,由子类实现。但目前主流使用方式不使用这套逻辑,而且有多种实现,所以本文不分析,后面单独写文章来分析。
getBeanFactory方法
该方法主要是获取上面创建的BeanFacory实例,bean工厂实例没有定义在AbstractApplicationContext类中,而是定义了一个模板方法,由子类来返回对象。
GenericApplicationContext中的实现
这里是直接返回该类定义的属性beanFactory。
java
spring-context/src/main/java/org/springframework/context/support/GenericApplicationContext.java
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
AbstractRefreshableApplicationContext中的实现
java
spring-context/src/main/java/org/springframework/context/support/AbstractRefreshableApplicationContext.java
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
DefaultListableBeanFactory beanFactory = this.beanFactory;
if (beanFactory == null) {
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
}
return beanFactory;
}
这里也是直接返回了本类的属性beanFactory。
总结
本文比较简单,主要是分析了BeanFactory的创建过程。主refresh方法中的后续步骤都会基于该bean工厂对象来进行。