上节我们在spring容器之Bean标签的解析中知道了我们最核心的bean标签的解析过程,在BeanDefinitionParserDelegate#parseBeanDefinitionElement()方法中完成,其中也有相关子元素的解析过程,如:meta标签以及lookup-method等标签的解析过程,这也是我们上篇遗留的问题,接下来我们看.
Meta标签解析
对于meta标签可能很多人都不清楚,这里简单的说一下:
<bean id="student" class="com.sgcc.bean.Student">
<property name="name" value="无敌"/>
<property name="age" value="20"/>
<meta key="test" value="myCase"/>
</bean>
在这段代码中,我们可以发现<meta>作为了bean标签的字标签来使用,我在配置中写的key是当需要bean的meta信息时,可以通过beanDefinition的getAttribute(key)方法进行获取
接下来我们来看spring是解析字标签meta的过程:
//解析子标签meta的过程
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
//获取当前节点的所有子元素
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//从所有子元素中拿到meta元素
if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
Element metaElement = (Element) node;
//获取meta的key和value
String key = metaElement.getAttribute(KEY_ATTRIBUTE);
String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
//通过获取到的key和value来构建BeanMetadataAttribute属性
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
//封装source属性
attribute.setSource(extractSource(metaElement));
//保存属性
attributeAccessor.addMetadataAttribute(attribute);
}
}
}
上述代码就是字标签meta的解析过程,简单的总结下:
- 首先是通过传入的参数ele,获取所有的子元素
NodeList nl = ele.getChildNodes();
- 接下来遍历所有的子元素,拿到我们想要的meta元素,于此同时获取key和value
public static final String META_ELEMENT = "meta";
Element metaElement = (Element) node;
//获取meta的key和value
String key = metaElement.getAttribute(KEY_ATTRIBUTE);
String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
- 通过获取到的key和value来构建BeanMetadataAttribute属性
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
这里有一个关于BeanMetadataAttribute的属性类,我们来看一下:
BeanMetadataAttribute
大概来说,BeanMetadataAttribute是表示bean元数据定义的信息,以key-value的形式存在,实质该属性属于beanDefinition的一部分,接着看它的继承实现关系和一些常用的方法:

public class BeanMetadataAttribute implements BeanMetadataElement {
private final String name; //key
@Nullable
private final Object value;
@Nullable
private Object source; //元数据的配置文件资源
/**
* Create a new AttributeValue instance.
* @param name the name of the attribute (never {@code null})
* @param value the value of the attribute (possibly before type conversion)
*/
public BeanMetadataAttribute(String name, @Nullable Object value) {
Assert.notNull(name, "Name must not be null");
this.name = name;
this.value = value;
}
/**
* Return the name of the attribute.
*/
public String getName() {
return this.name;
}
/**
* Return the value of the attribute.
*/
@Nullable
public Object getValue() {
return this.value;
}
/**
* Set the configuration source {@code Object} for this metadata element.
* <p>The exact type of the object will depend on the configuration mechanism used.
*/
public void setSource(@Nullable Object source) {
this.source = source;
}
@Override
@Nullable
public Object getSource() {
return this.source;
}
我们从它的家族图可以看出,实现了BeanMetadataElement接口,而该接口中只有一个获取元数据配置资源的方法,对于它本身来说,方法简单这里就不说了,接着看
- 属性的封装
attributeAccessor.addMetadataAttribute(attribute);
封装过程中调用了BeanMetadataAttributeAccessor#addMetadataAttribute方法,这里首先看一下BeanMetadataAttributeAccessor类的作用
BeanMetadataAttributeAccessor
该类的主要的作用是将属性进行封装成BeanMetadataAttribute对象,来看一下的它的继承关系

有图可以看出BeanMetadataAttributeAccessor类直接继承AttributeAccessorSupport且实现了BeanMetadataElement接口,直接看代码:
public class BeanMetadataAttributeAccessor extends AttributeAccessorSupport implements BeanMetadataElement {
@Nullable
private Object source;
/**
* Set the configuration source {@code Object} for this metadata element.
* <p>The exact type of the object will depend on the configuration mechanism used.
*/
//封装source
public void setSource(@Nullable Object source) {
this.source = source;
}
@Override
@Nullable
public Object getSource() {
return this.source;
}
/**
* Add the given BeanMetadataAttribute to this accessor's set of attributes.
* @param attribute the BeanMetadataAttribute object to register
*/
//保存
public void addMetadataAttribute(BeanMetadataAttribute attribute) {
super.setAttribute(attribute.getName(), attribute);
}
/**
* Look up the given BeanMetadataAttribute in this accessor's set of attributes.
* @param name the name of the attribute
* @return the corresponding BeanMetadataAttribute object,
* or {@code null} if no such attribute defined
*/
@Nullable
public BeanMetadataAttribute getMetadataAttribute(String name) {
return (BeanMetadataAttribute) super.getAttribute(name);
}
@Override
public void setAttribute(String name, @Nullable Object value) {
super.setAttribute(name, new BeanMetadataAttribute(name, value));
}
@Override
@Nullable
public Object getAttribute(String name) {
BeanMetadataAttribute attribute = (BeanMetadataAttribute) super.getAttribute(name);
return (attribute != null ? attribute.getValue() : null);
}
@Override
@Nullable
public Object removeAttribute(String name) {
BeanMetadataAttribute attribute = (BeanMetadataAttribute) super.removeAttribute(name);
return (attribute != null ? attribute.getValue() : null);
}
}
这就是BeanMetadataAttributeAccessor类的方法,以上关于字标签meta整个的解析过程,后续来说其他的......
网友评论