• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

详解Spring IOC 容器启动流程分析

java 搞代码 4年前 (2022-01-09) 22次浏览 已收录 0个评论

使用 Spring 时,XML 和注解是使用得最多的两种配置方式,虽然是两种完全不同的配置方式,但对于 IOC 容器来说,两种方式的不同主要是在 BeanDefinition 的解析上。而对于核心的容器启动流程,仍然是一致的。

AbstractApplicationContext 的 refresh 方法实现了 IOC 容器启动的主要逻辑,启动流程中的关键步骤在源码中也可以对应到独立的方法。接下来以  AbstractApplicationContext 的实现类  ClassPathXmlApplicationContext 为主 ,并对比其另一个实现类 AnnotationConfigApplicationContext , 解读 IOC 容器的启动过程。

AbstractApplicationContext.refresh

@Override
 public void refresh() throws BeansException, IllegalStateException {
 synchronized (this.startupShutdownMonitor) {
  // Prepare this context for refreshing.
  prepareRefresh();

  // Tell the subclass to refresh the internal bean factory.
  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.
  postProcessBeanFactory(beanFactory);

  // Invoke factory processors registered as beans in the context.
  invokeBeanFactoryPostProcessors(beanFactory);

  // Register bean processors that intercept bean creation.
  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.
  finishBeanFactoryInitialization(beanFactory);

  // Last step: publish corresponding event.
  finishRefresh();
  }

  // ...
 }
 }

ApplicationContext 和 BeanFactory 的关系

ClassPathXmlApplicationContext 和  AnnotationConfigApplicationContext 的继承树如下所示。两者都继承自  AbstractApplicationContext 。

 

ApplicationContext 继承树( 高清大图 )

 

BeanFactory 继承树( 高清大图 )

ApplicationContext 是 IOC 容器的承载体,而  BeanFactory 是操作这个容器的工具,两者关系紧密,相互协作。 refresh 方法实现了 ApplicationContext 和 BeanFactory 相互协作的主要过程,不同之处主要在子类  AbstractRefreshableApplicationContext 和 GenericApplicationContext 中实现,两者使用的 BeanFactory 都为 DefaultListableBeanFactory , DefaultListableBeanFactory 的定义如下:

DefaultListableBeanFactory :

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
  implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable

可见 DefaultListableBeanFactory 实现了  ConfigurableListableBeanFactory ,意味着是可配置,可遍历的,至于为什么可以,让我们继续往下寻找找答案。

BeanDefinition 的获取

DefaultListableBeanFactory 中使用 Map 结构保存所有的 BeanDefinition 信息:

DefaultListableBeanFactory :

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);


ClassPathXmlApplicationContext 中的解析
使用 BeanDefinitionDocumentReader (可参看 DefaultBeanDefinitionDocumentReader.processBeanDefinition 方法) 将 xml 中<strong>本文来源gaodaima#com搞(代@码$网6</strong>的 bean 解析为 BeanDefinition , 然后由 BeanDefinitionRegistry 注册到 BeanFactory 中。 入口: AbstractApplicationContext.refreshBeanFactory (在 refresh 中调用)

AnnotationConfigApplicationContext 中的解析
通过 BeanDefinitionScanner 扫描 Bean 声明,解析为 BeanDefinition 并由 BeanDefinitionRegistry 注册到 BeanFactory 中。 入口: AnnotationConfigApplicationContext 的构造函数。

为什么 ClassPathXmlApplicationContext 的入口是在 refreshBeanFactory 方法中 ?
AbstractApplicationContext.refreshBeanFactory 定义如下:

AbstractApplicationContext :

protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:详解Spring IOC 容器启动流程分析
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址