Spring核心IOC源码解读(一)获取BeanFactory
在 AbstractApplicationContext.refresh(); 的过程中,第二步为获取BeanFactory -> obtainFreshBeanFactory()。在这个方法中,Spring先创建了BeanFactory,然后通过读取XML配置文件(或者扫描Java类)的方式初始化了BeanDefinition。这里面就包括Spring Bean的主要信息,例如依赖情况、作用域等等。
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // (1)Prepare this context for refreshing. prepareRefresh(); // (2)Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); ...... }
一、 obtainFreshBeanFactory() 方法的具体内容
/** * Tell the subclass to refresh the internal bean factory. * @return the fresh BeanFactory instance * @see #refreshBeanFactory() * @see #getBeanFactory() */ protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); return getBeanFactory(); }
注释上写的:告诉子类刷新内部的BeanFactory
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
refreshBeanFactory() 、 getBeanFactory() 方法是抽象方法,由子类实现,这里的子类是 AbstractRefreshableApplicationContext ,它是 AbstractApplicationContext 的子类。(类图可以参考:大纲)
二、关键在于 refreshBeanFactory() 方法
看看 AbstractRefreshableApplicationContext 的实现:
@Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try {
//(1)初始化BeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory);
//(2)读取BeanFefinition loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
(1) AbstractRefreshableApplicationContext.createBeanFactory()
创建 DefaultListableBeanFactory 对象,这个对象的类图关系如下
不仅实现了BeanFactory,还实现了Registry相关接口,意味着和Bean的注册有很大关系
(2) AbstractRefreshableApplicationContext.loadBeanDefinitions()
loadBeanDefinitions() 是一个抽象方法,由 AbstractXmlApplicationContext 实现,类图可参考:大纲
@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // (1)创建读取Xml的对象,和BeanFactory是依赖关系 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // (2)这些都是一些初始化操作 beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // (3)真正的初始化操作发生在最后一步loadBeanDefinitions initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); }
XmlBeanDefinitionReader 初始化的 beanFactory 对象是 BeanDefinitionRegistry 接口的实现
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) { super(registry); }
三、 loadBeanDefinitions(beanDefinitionReader); 通过Reader将XML Bean信息读取到BeanFactory中
BeanFactory和Reader之间的关系是依赖关系
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
reader.loadBeanDefinitions(configLocations) 方法中,将String类型的xml文件地址转为了Resource对象,下面就是通过流来读取👇
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { .... try (InputStream inputStream = encodedResource.getResource().getInputStream()) { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } .... }
层层抽丝剥茧之后,走到了 DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root); 中
protected void doRegisterBeanDefinitions(Element root) { ... preProcessXml(root); //核心步骤 parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; ... }
四、看看 DefaultBeanDefinitionDocumentReader 是如何解析Bean的
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //(1)将XML文件中类名、别名、属性值初始化到了BeanDefinition中,并初始化一些默认值,并依赖到了Holder对象中 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //(2)装饰 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); //(3)这一步的操作就是将BeanDefinition放入DefaultListableBeanFactory对象的beanDefinitionMap属性中 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); ... } }
最重要的就是第一步将BeanDefinition初始化之后,第三步放入beanDefinitionMap中