Spring解析XML文件,其实就是构造一个 BeanDefinition 对象的过程。
BeanDefinition 是一个接口,它描述了一个 Bean 实例,实例中的参数,即配置文件中的属性。
它继承 AttributeAccessor 和 BeanMetadataElement 接口。两个接口定义如下:
getSource()
方法来获取。 由图可知,我们常用的三个实现类有:ChildBeanDefinition、GenericBeanDefinition、RootBeanDefinition,三者都继承 AbstractBeanDefinition。如果配置文件中定义了父
和 子
,则父
用 RootBeanDefinition表示,子
用 ChildBeanDefinition 表示,而没有父
的就使用RootBeanDefinition 表示。GenericBeanDefinition 为一站式服务类。AbstractBeanDefinition对三个子类共同的类信息进行抽象。
解析Bean:
在BeanDefinitionParserDelegate类的parseBeanDefinitionElement方法中,完成解析。
进入createBeanDefinition方法中可知,它创建了一个GenericBeanDefinition对象返回给AbstractBeanDefinition
接下来如方法名所示,依次调用方法,解析XML标签,并为AbstractBeanDefinition实例赋值:
setDescription:description元素;
parseMetaElements:Meta元素;
parseLookupOverrideSubElements:lookup-method元素;
parseReplacedMethodSubElements:replace-method元素;
parseConstructorArgElements:constructor-arg元素;
parsePropertyElements:property元素;
parseQualifierElements:qualify元素;
学习时,因为配置了Meta元素但是不会读取,因此特为Meta元素说明。
在parseMetaElements,可以看出,从Meta标签读取key和value后,将之存入了BeanMetadataAttribute对象,并最终通过addMetadataAttribute方法存入attributeAccessor对象中。
BeanMetadataAttributeAccessor类是AbstractBeanDefinition接口的父类。
所以我们如果想读取Meta元素的内容,需要从attributeAccessor对象中读取;看看attributeAccessor在哪里?
该方法被parseBeanDefinitionElement调用,在该方法的最后,new了一个BeanDefinitionHolder对象;然后把值存在了beanDefinition中。
返回了的BeanDefinitionHolder去了哪里?
方法先被parseBeanDefinitionElement调用,而parseBeanDefinitionElement方法又被DefaultBeanDefinitionDocumentReader类中的processBeanDefinition方法调用。
在BeanDefinitionReaderUtils.registerBeanDefinition中,有一个registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());方法,用来注册BeanDefinition。
Spring的最基本接口就是BeanFactory,而BeanFactory最常用的实现类就是DefaultListableBeanFactory,不难想象,BeanDefinition一定是在这个类中,存在了Spring容器里。结果也的确是。
BeanDefinitionMap便是Spring存放Bean的容器。
至此,BeanDefinition便存储好了。当想读取Meta元素时,要先获取BeanDefinition实例。
这里只能使用DefaultListableBeanFactory,因为其他的Spring容器需要new一个DefaultListableBeanFactory,而这样,BeanDefinitionMap是空的,会导致查不出来数据。
getBeanDefinition会根据String从BeanDefinitionMap中查询一个BeanDefinition实例,从这个实例中,getAttribute即可获取Meta元素的value值。
输出结果: