在Spring源码分析容器篇中提到将spring中的bean解析并注入到beanFactory中,当时因为容器篇幅太长仅仅是一笔带过,本文是对spring加载bean中生成BeanDefinition的详细分析,也是笔者对spring深入学习的过程,文中有出错的地方,还望大家能够及时指出。
本次入口分析是Spring容器篇中第二步obtainFreshBeanFactory#…#loadBeanDefinitions方法,obtainFreshBeanFactory方法是包含了创建容器和解析配置并生成BeanDefinition,创建容器是由DefaultListableBeanFactory直接创建,而解析配置文件是本文重点分析的对象。
Spring源码的风格是将一切比较复杂的方法进行封装和抽象,便于其他地方可调用,然而真正意义上在干活的,也是我们所关心的是do-*开头的方法才是具体实现的地方,loadBeanDefinitions(resource)->loadBeanDefinitions(encodedResource)->doLoadBeanDefinitions,代码如下:
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));//进行编码封装配置资源
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try (InputStream inputStream = encodedResource.getResource().getInputStream()) {//获取资源输入流
InputSource inputSource = new InputSource(inputStream);//流转化
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());//开始调用真正解析BeanDefinition
}catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
在spring进行一系列的包装、封装和转化操作后,进行调用doLoadBeanDefinitions对配置文件进行解析,首先是先对文件进行文档化Document转化,然后对doc进行标签解析并调用registerBeanDefinitions方法,主要就是根据配置文件中的各种标签和属性,进行封装BeanDefinition,代码如下:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);//文件转化为文档类,底层是转化包,此处不多解释
int count = registerBeanDefinitions(doc, resource);//生成BeanDefinition,重点分析
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
//后面一连串的catch是捕获异常,便于spring能精确提示出解析异常
}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);
}
}
根据上述方式中转化后的文档类进行注册BeanDefinition,创建读取对象,然后根据读取对象进行封装,如下:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();//创建读取器
int countBefore = getRegistry().getBeanDefinitionCount();//统计已存在的BeanDefinition数量
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//解析doc并生成BeanDefinition
return getRegistry().getBeanDefinitionCount() - countBefore;//此次文件解析的数量
}
spring源码风格,概念封装,实际干活的是doRegisterBeanDefinitions,一笑而过,继续看码:
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
protected void doRegisterBeanDefinitions(Element root) {
this.delegate = createDelegate(getReaderContext(), root, parent);//创建委托类对象
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);//是否有profile属性设置,个性化属性生效
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root);//预解析前子类重写,开放性设计,此处方法是默认为空
parseBeanDefinitions(root, this.delegate);//核心点,真正开始处理各种标签和bean
postProcessXml(root);//解析后子类重写,开放性设计,默认为空实现
this.delegate = parent;
}
望眼欲穿的点终于被发现,parseBeanDefinitions生成各种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)) {//spring默认的定义空间,则使用默认的解析如配置文件指定的bean
parseDefaultElement(ele, delegate);//普通的import、alias、bean、beans中被定义的bean
}else{
delegate.parseCustomElement(ele);//采用自定义的,比如采用tx定义命名空间、jdbc命名等等
}
}
}
}else{
delegate.parseCustomElement(root);
}
}
Spring支持普通的import、alias、bean、beans中被定义的bean,本文主要是分析配置文件XMl定义的bean解析,注解方式实现的bean会放到后面分析Springboot实现方式时去重点分析,原理其实相差不多,直接上干货,parseDefaultElement代码如下:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {//import文件外部导入文件中解析
importBeanDefinitionResource(ele);
}else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {//alias别名bean处理
processAliasRegistration(ele);
}else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {//bean标签处理(也是配置文件中使用比较常用的,重点分析)
processBeanDefinition(ele, delegate);
}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {//beans标签处理
doRegisterBeanDefinitions(ele);
}
}
在Spring配置文件中,比较核心、常见的也是bean标签定义Bean,同时最复杂的也是processBeanDefinition(重点分析),代码如下:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//返回BeanDefinitionHolder对象,包含基本bean属性、元素
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {//判断bdHolder对象不为空时会判断是否存在子节点,持续解析
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//将bdHolder注册到容器中
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
//发送事件通知,通知想关的监听器,表明bean加载完毕
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
Spring的bean标签属性或元素解析,交由BeanDefinitionParserDelegate类来具体解析,parseBeanDefinitionElement代码如下:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
bean标签具体解析内容:id、name和多个name名称、别名alias、beanName唯一性检查,生成beanDefinition(实际上是GenericBeanDefinition生成),beanName是否命名等步骤,最后生成使用生成的beanDefinition来封装BeanDefinitionHolder实例,逻辑代码如下:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE);//id属性获取
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);//name属性获取
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {//别名处理
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {//去除别名中第一个beanName值
beanName = aliases.remove(0);
if (logger.isTraceEnabled()) {
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
//检查beanName唯一性
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
//使用GenericBeanDefinition封装beanDefinition的各种属性
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
//beanName不存在,则采用spring默认的命名规则
if (containingBean != null) {//当前BeanDefinition已存在,则使用generateBeanName方法默认生成
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}else{
//不存在containingBean时则使用Spring自身定义的beanName和CLassName的相关约束
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isTraceEnabled()) {
logger.trace("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
Spring对bean标签的属性采用硬编码处理方式,分别使用了以下八个核心点来处理,如下①②③④⑤⑥⑦⑧所示:
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {//处理bean标签中的属性class
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {//处理bean标签中的属性parent
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
//使用GenericBeanDefinition来生成AbstractBeanDefinition实例,代码如①
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//spring内置处理bean属性的硬编码处理逻辑,代码如②
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));//description属性处理
parseMetaElements(ele, bd);//解析元数据如③
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());//解析lookup-method如④
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());//解析replaced-method如⑤
parseConstructorArgElements(ele, bd);//解析构造函数参数如⑥
parsePropertyElements(ele, bd);//解析property子元素如⑦
parseQualifierElements(ele, bd);//解析qualifier子元素如⑧
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
GenericBeanDefinition类创建具体实例,具体代码如下
protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
throws ClassNotFoundException {
return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
}
public static AbstractBeanDefinition createBeanDefinition(
@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null) {
if (classLoader != null) {
bd.setBeanClass(ClassUtils.forName(className, classLoader));
}
else {
bd.setBeanClassName(className);
}
}
return bd;
}
bean属性:singleton、scope、abstract、lazy、autowire、depends_on、autowire_candidate、primary、init_method、destroy_method、factory_method和factory_bean,具体代码如下:
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
BeanDefinition containingBean, AbstractBeanDefinition bd) {
//处理singleton属性
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
}else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {//处理scope属性
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
}else if (containingBean != null) {
bd.setScope(containingBean.getScope());
}
//处理abstract属性
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
//处理lazy懒加载属性
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (isDefaultValue(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
//处理自动注入属性autowire
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
bd.setAutowireMode(getAutowireMode(autowire));
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {//处理depends_on依赖
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
}
//处理autowire_candidate属性
String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
if (isDefaultValue(autowireCandidate)) {
String candidatePattern = this.defaults.getAutowireCandidates();
if (candidatePattern != null) {
String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
}
}else {
bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
}
//处理bean的primary属性
if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
}
//处理初始方法属性init_method
if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
bd.setInitMethodName(initMethodName);
}else if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
//处理destroy_method销毁方法属性
if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
bd.setDestroyMethodName(destroyMethodName);
}else if (this.defaults.getDestroyMethod() != null) {
bd.setDestroyMethodName(this.defaults.getDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
//处理factory_method属性
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
//处理factory_bean属性
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
return bd;
}
代码如下:
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
Element metaElement = (Element) node;
String key = metaElement.getAttribute(KEY_ATTRIBUTE);
String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
attribute.setSource(extractSource(metaElement));
attributeAccessor.addMetadataAttribute(attribute);
}
}
}
代码如下:
public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
Element ele = (Element) node;
String methodName = ele.getAttribute(NAME_ATTRIBUTE);
String beanRef = ele.getAttribute(BEAN_ELEMENT);
LookupOverride override = new LookupOverride(methodName, beanRef);
override.setSource(extractSource(ele));
overrides.addOverride(override);
}
}
}
代码如下:
public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
Element replacedMethodEle = (Element) node;
String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);//name属性
String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);//回调方法
ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT);
for (Element argTypeEle : argTypeEles) {
String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE);
match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
if (StringUtils.hasText(match)) {
replaceOverride.addTypeIdentifier(match);
}
}
replaceOverride.setSource(extractSource(replacedMethodEle));
overrides.addOverride(replaceOverride);
}
}
}
代码如下:
public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
parseConstructorArgElement((Element) node, bd);
}
}
}
代码如下:
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
parsePropertyElement((Element) node, bd);
}
}
}
代码如下:
public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) {
parseQualifierElement((Element) node, bd);
}
}
}