Spring的XML解析原理,这一次全搞懂再走( 二 )
这个方法是一个典型的模板方法模式的实现 , 第一步是准备初始化容器环境 , 这一步不重要 , 重点是第二步 , 创建BeanFactory对象、加载解析xml并封装成BeanDefinition对象都是在这一步完成的 。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();return getBeanFactory(); }
点进去看是调用了refreshBeanFactory方法 , 但这里有两个实现 , 应该进哪一个类里面呢?
文章插图
如果你还记得前面的继承体系 , 那你就会毫不犹豫的进入AbstractRefreshableApplicationContext类中 , 所以在阅读源码的过程中一定要记住类的继承体系 。
protected final void refreshBeanFactory() throws BeansException {//如果BeanFactory不为空 , 则清除BeanFactory和里面的实例if (hasBeanFactory()) {destroyBeans();closeBeanFactory();}try {//创建DefaultListableBeanFactoryDefaultListableBeanFactory beanFactory = createBeanFactory();beanFactory.setSerializationId(getId());//设置是否可以循环依赖 allowCircularReferences//是否允许使用相同名称重新注册不同的bean实现.customizeBeanFactory(beanFactory);//解析xml , 并把xml中的标签封装成BeanDefinition对象loadBeanDefinitions(beanFactory);synchronized (this.beanFactoryMonitor) {this.beanFactory = beanFactory;}}catch (IOException ex) {throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);} }
在这个方法中首先会清除掉上一次创建的BeanFactory和对象实例 , 然后创建了一个DefaultListableBeanFactory对象并传入到了loadBeanDefinitions方法中 , 这也是一个模板方法 , 因为我们的配置不止有xml , 还有注解等 , 所以这里我们应该进入AbstractXmlApplicationContext类中:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {//创建xml的解析器 , 这里是一个委托模式XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// Configure the bean definition reader with this context's// resource loading environment.beanDefinitionReader.setEnvironment(this.getEnvironment());//这里传一个this进去 , 因为ApplicationContext是实现了ResourceLoader接口的beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));// Allow a subclass to provide custom initialization of the reader,// then proceed with actually loading the bean definitions.initBeanDefinitionReader(beanDefinitionReader);//主要看这个方法loadBeanDefinitions(beanDefinitionReader); }
首先创建了一个XmlBeanDefinitionReader对象 , 见名知意 , 这个就是解析xml的类 , 需要注意的是该类的构造方法接收的是BeanDefinitionRegistry对象 , 而这里将DefaultListableBeanFactory对象传入了进去(别忘记了这个对象是实现了BeanDefinitionRegistry类的) , 如果你足够敏感 , 应该可以想到后面会委托给该类去注册 。 注册什么呢?自然是注册BeanDefintion 。 记住这个猜想 , 我们稍后来验证是不是这么回事 。 接着进入loadBeanDefinitions方法获取之前保存的xml配置文件路径 , 并委托给XmlBeanDefinitionReader对象解析加载:
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {Resource[] configResources = getConfigResources();if (configResources != null) {reader.loadBeanDefinitions(configResources);}//获取需要加载的xml配置文件String[] configLocations = getConfigLocations();if (configLocations != null) {reader.loadBeanDefinitions(configLocations);} }
最后会进入到抽象父类AbstractBeanDefinitionReader中:
public int loadBeanDefinitions(String location, @Nullable Set
- 小米科技|性价比拉满!TCL T8E-PRO QLED智屏当属潮玩世代的必备单品
- 华为鸿蒙系统|华为汽车战略布局,进入汽车行业的底气来自哪里?(车车佳)
- 浙江省|浙江的五大富豪,四位做过中国首富,仅马云的阿里就1年纳税366亿
- iOS|恒创科技:Linux日本云服务器安全设置的基本步骤
- javascript|手机移动端的PyTorch来了,还支持JavaScript
- 中关村|柳传志在这里被骗、掘金,书写半部科技史的中关村经历了什么?
- 手机维修|手机维修的猫腻‖你是不是上当了?
- 智能化|感知局限下,车路协同的“子弹”还得再飞会儿
- 华为鸿蒙系统|都2021年底了,为何Mate40Pro还是目前公认最好用的“安卓”手机
- saas|上半年的Redmi K40 Pro,现在入手2500元不到,还等?