1、DefaultListableBeanFactory
1.1 类的结构

DefaultListableBeanFactory是整个bean加载的核心部分,是Spring注册及加载的bean的默认实现。DefaultListableBeanFactory继承了AbstractAutowireCapableBeanFactory并实现了ConfigurableListableBeanFactory以及BeanDefinitionRegistry接口。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable
1.2 XmlBeanFactory
XmlBeanFactory对父类DefaultListableBeanFactory进行了扩展,主要用于从XML文档中读取BeanDefinition,对于注册及获取bean都是使用从父类DefaultListableBeanFactory继承的方法区实现,而唯独与父类不同的个性化实现就是增加了XmlBeanDefinitionReader类型的reader属性。在XmlBeanFactory中主要使用reader属性对资源文件进行读取和注册;
//## 对资源文件进行读取和注册 ##//private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
1.2.1 XmlBeanDefinitionReader
- 继承AbstractBeanDefinitionReader中的方法,来使用ResourceLoader将资源文件路径转换为对应的Resource文件。
- 通过DocumentLoader对Resource文件进行转换,将Resource文件转换为Document文件。
- 通过实现接口BeanDefinitionDocumentReader的DefaultBeanDefinitionDocumentReader对Document进行解析,并使用BeanDefinitionParserDelegate对Element进行解析。
1.3ClassPathResource
Spring的配置文件读取是通过ClassPathResource进行封装的。
Spring对其内部使用到的资源实现了自己的抽象结构:Resource接口封装底层资源。
当通过Resource相关类完成了对配置文件进行封装后,配置文件的读取功能就全权交给XmlBeanDefinitionReader来处理了。
2、源码
public XmlBeanFactory(Resource resource) throws BeansException {//调用XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)构造方法this(resource, null);}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {//parentBeanFactory为父类BeanFactory用于factory合并,可以为空super(parentBeanFactory);//资源加载的真正实现this.reader.loadBeanDefinitions(resource);}
2.1 核心逻辑部分loadBeanDefinitions
封装资源文件。当进入XmlBeanDefinitionReader后首先对参数Resource使用EncodedResource类进行封装。
/*** Load bean definitions from the specified XML file.* @param resource the resource descriptor for the XML file* @return the number of bean definitions found* @throws BeanDefinitionStoreException in case of loading or parsing errors*/@Overridepublic int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {//## 1、封装资源文件 ##//return loadBeanDefinitions(new EncodedResource(resource));}
获取输入流。从Resource中获取对应的InputStream并构造InputSource。
通过构造的InputSource实例和Resource实例继续调用函数doLoadBeanDefinitions。
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {Assert.notNull(encodedResource, "EncodedResource must not be null");if (logger.isInfoEnabled()) {logger.info("Loading XML bean definitions from " + encodedResource);}//## 通过属性来记录已经加载的资源 ##//Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();if (currentResources == null) {currentResources = new HashSet<>(4);this.resourcesCurrentlyBeingLoaded.set(currentResources);}if (!currentResources.add(encodedResource)) {throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");}try {//## 2、获取输入流 ##//InputStream inputStream = encodedResource.getResource().getInputStream();try {//## 2.1 构造InputSource实例 ##////## InputSource这个类并不来自于Spring,它的全路径是 org.xml.sax.InputSource ##//InputSource inputSource = new InputSource(inputStream);if (encodedResource.getEncoding() != null) {inputSource.setEncoding(encodedResource.getEncoding());}//## 3、通过InputSource实例和Resource实例继续调用函数 ##////## 真正进入了逻辑核心部分 ##//return doLoadBeanDefinitions(inputSource, encodedResource.getResource());}finally {//## 关闭输入流 ##//inputStream.close();}}catch (IOException ex) {throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), ex);}finally {currentResources.remove(encodedResource);if (currentResources.isEmpty()) {this.resourcesCurrentlyBeingLoaded.remove();}}}
2.1 核心处理部分doLoadBeanDefinitions
- 获取对XML文件的验证模式
- 加载XML文件,并得到相应的Document
根据返回的Document注册Bean信息
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {try {//## 1、getValidationModeForResource 获取XML文件的验证模式 ##////## 2、加载XML文件,并得到对应Document ##//Document doc = doLoadDocument(inputSource, resource);//## 根据返回的Document注册Bean信息 ##//return registerBeanDefinitions(doc, resource);}catch (BeanDefinitionStoreException ex) {throw ex;}catch (SAXParseException ex) {throw new XmlBeanDefinitionStoreException(resource.getDescription(),"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);}catch (SAXException ex) {throw new XmlBeanDefinitionStoreException(resource.getDescription(),"XML document from " + resource + " is invalid", ex);}catch (ParserConfigurationException ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"Parser configuration exception parsing XML from " + resource, ex);}catch (IOException ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"IOException parsing XML document from " + resource, ex);}catch (Throwable ex) {throw new BeanDefinitionStoreException(resource.getDescription(),"Unexpected exception parsing XML document from " + resource, ex);}}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {//## 使用DefaultBeanDefinitionDocumentReader 实例化 BeanDefinitionDocumentReader ##//BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();//## 记录统计前 BeanDefinition 的加载个数 ##//int countBefore = getRegistry().getBeanDefinitionCount();//## 加载及注册bean BeanDefinitionDocumentReader是一个接口,真正的类型其实已经是DefaultBeanDefinitionDocumentReader ##//documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//## 记录本次加载 BeanDefinition 的个数 ##//return getRegistry().getBeanDefinitionCount() - countBefore;}
2.3核心逻辑的底部doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {// Any nested <beans> elements will cause recursion in this method. In// order to propagate and preserve <beans> default-* attributes correctly,// keep track of the current (parent) delegate, which may be null. Create// the new (child) delegate with a reference to the parent for fallback purposes,// then ultimately reset this.delegate back to its original (parent) reference.// this behavior emulates a stack of delegates without actually necessitating one.BeanDefinitionParserDelegate parent = this.delegate;//## 专门处理解析BeanDefinitionParserDelegate类型的实例 ##//this.delegate = createDelegate(getReaderContext(), root, parent);if (this.delegate.isDefaultNamespace(root)) {//## 处理profile属性 ##//String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);if (StringUtils.hasText(profileSpec)) {String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {if (logger.isInfoEnabled()) {logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +"] not matching: " + getReaderContext().getResource());}return;}}}//## 解析处理处理,留给子类实现 ##//preProcessXml(root);//## 解析并注册bean ##//parseBeanDefinitions(root, this.delegate);//## 解析后处理,留给子类实现 ##//postProcessXml(root);this.delegate = parent;}
2.4 解析并注册BeanDefinition
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {if (delegate.isDefaultNamespace(root)) {NodeList nl = root.getChildNodes();for (int i = 0; i < nl.getLength(); i++) {Node node = nl.item(i);if (node instanceof Element) {Element ele = (Element) node;if (delegate.isDefaultNamespace(ele)) {//## 对bean处理 默认解析 ##//parseDefaultElement(ele, delegate);}else {//## 对bean处理 自定义解析 ##//delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);}}
2.4.1 默认标签的解析
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {//## 对import标签的处理 ##//if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);}//## 对alias标签的处理 ##//else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);}//## 对bean标签的处理 ##//else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {processBeanDefinition(ele, delegate);}//## 对beans标签的处理 ##//else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);}}
bean标签的解析及注册
- 首先委托BeanDefinitionParserDelegate类的方法parseBeanDefinitionElement方法进行元素解析,返回BeanDefinitionHolder类型的实例bdHolder(包含我们配置文件的各种属性,如:class、name、id、alias之类的属性)。
- 当返回的bdHolder不为空的情况下若存在默认标签的子节点下再有自定义属性,还需要对自定义标签再次解析。
- 解析完成后,需要对解析后的bdHolder进行注册。
最后发出响应事件。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {//## 委托BeanDefinitionParserDelegate类的方法parseBeanDefinitionElement进行元素解析 ##////## BeanDefinitionHolder的实例bdHolder 已经包含我们配置文件中配置的各种属性了,例如:class、name、id、alias ##//BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) {//## 若存在默认标签的子节点下再有自定义属性,还需要对自定义属性进行解析 ##//bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// Register the final decorated instance.//## 解析完成后,需要对bdHolder进行注册 ##//BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());}catch (BeanDefinitionStoreException ex) {getReaderContext().error("Failed to register bean definition with name '" +bdHolder.getBeanName() + "'", ele, ex);}// Send registration event.//## 通知监听器解析及注册完成 ##//getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));}}
2.4.1.1 创建用于属性承载的BeanDefinition
BeanDefinition是一个接口,在Spring中存在三种实现,RootBeanDefinition、ChildBeanDefinition以及GenericBeanDefinition。三种实现均继承AbstractBeanDefinition,其中BeanDefinition是配置文件
元素标签在容器中的内部标识形式。 2.4.1.2 注册解析的BeanDefinition
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.//## 使用beanName做唯一标识注册 ##//String beanName = definitionHolder.getBeanName();registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// Register aliases for bean name, if any.//## 注册所以别名 ##//String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String alias : aliases) {registry.registerAlias(beanName, alias);}}}
通过beanName注册BeanDefinition
-
2.4.1.3 通知监听器解析及注册完成
