参考文章:
解析方法
bean解析的方法在:DefaultBeanDefinitionDocumentReader.processBeanDefinition(ele, delegate);
相关代码解读在 完成注册
- 调用
BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element ele, BeanDefinitionParserDelegate delegate)
方法,进行元素解析。- 如果解析失败,则返回
null
,错误由 ProblemReporter 处理。 - 如果解析成功,则返回 BeanDefinitionHolder 实例
bdHolder
。BeanDefinitionHolder 为持有name
和alias
的 BeanDefinition。 - 详细解析,见 「2. parseBeanDefinitionElement」 。
- 如果解析失败,则返回
- 若实例
bdHolder
不为空,则调用BeanDefinitionParserDelegate#decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder bdHolder)
方法,进行自定义标签处理。 - 解析完成后,则调用
BeanDefinitionReaderUtils#registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
方法,对bdHolder
进行 BeanDefinition 的注册。 - 发出响应事件,通知相关的监听器,完成 Bean 标签解析。
parseBeanDefinitionElement
对属性进行解析并封装成 AbstractBeanDefinition 实例
// 进行 bean 元素解析。
// 如果解析成功,则返回 BeanDefinitionHolder 对象。而 BeanDefinitionHolder 为 name 和 alias 的 BeanDefinition 对象
// 如果解析失败,则返回 null 。
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element ele, BeanDefinitionParserDelegate delegate)
方法,进行<bean>
元素解析
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
// 解析ID和name
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
// 别名列表
List<String> aliases = new ArrayList<>();
// 保存别名
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
// 类名优先使用ID
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
// 假如不存在,则使用别名的第一个
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);
}
// 解析属性 构造AbstractBeanDefinition
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
// 重新生成唯一的beanName
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
// 生成唯一的 beanName
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
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;
}
}
// 创建 BeanDefinitionHolder 对象
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
beanName验证
/**
* 如果 id 不为空,则 beanName = id 。
* 如果 id 为空,但是 aliases 不空,则 beanName 为 aliases 的第一个元素
* 如果两者都为空,则根据默认规则来设置 beanName
*/
protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {
String foundName = null;
//寻找是否 beanName 已经使用
if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) {
foundName = beanName;
}
if (foundName == null) {
foundName = CollectionUtils.findFirstMatch(this.usedNames, aliases);
}
// 若已使用,使用 problemReporter 提示错误
if (foundName != null) {
error("Bean name '" + foundName + "' is already used in this <beans> element", beanElement);
}
this.usedNames.add(beanName);
this.usedNames.addAll(aliases);
}
parseBeanDefinitionElement
#parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean)
方法,对属性进行解析并封装成 AbstractBeanDefinition 实例
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
//解析class
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
//解析parent
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
// 初始化AbstractBeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//解析类属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//设置描述
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//解析meta属性,元数据
parseMetaElements(ele, bd);
//解析 lookupOverride 代码实现
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析 ReplacedMethod 方法替换配置
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析 ConstructorArg 属性
parseConstructorArgElements(ele, bd);
//解析 Property 属性
parsePropertyElements(ele, bd);
//解析 Qualifier 属性
parseQualifierElements(ele, bd);
//设置 资源
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;
}
createBeanDefinition
创建 GenericBeanDefinition 对象,并设置
parentName
、className
、beanClass
属性
protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
throws ClassNotFoundException {
return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
}
//初始化一个空的bean,并设置parent名字和类名
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;
}
parseBeanDefinitionAttributes
再调用
#parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd)
方法,该方法将创建好的 GenericBeanDefinition 实例当做参数,对bean
标签的所有属性进行解析
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
// 解析 scope 属性
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
}
else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
}
else if (containingBean != null) {
// Take default from containing bean in case of an inner bean definition.
bd.setScope(containingBean.getScope());
}
// 解析 abstract 属性
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
// 解析 lazy_init属性
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));
// 解析 depends-on 属性
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
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));
}
// 解析 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));
}
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
return bd;
}
完成 bean
标签的基本属性解析会依次调用
#parseMetaElements(lement ele, BeanMetadataAttributeAccessor attributeAccessor):
对子元素meta完成解析
#parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides):
对lookup-method完成解析
#parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides)
:
对replace-method
完成解析
<meta>
:元数据。<lookup-method>
:Spring 动态改变 bean 里方法的实现。方法执行返回的对象,使用 Spring 内原有的这类对象替换,通过改变方法返回值来动态改变方法。内部实现为使用 cglib 方法,重新生成子类,重写配置的方法和返回对象,达到动态改变的效果。
<replace-method>
:Spring 动态改变 bean 里方法的实现。需要改变的方法,使用 Spring 内原有其他类(需要继承接口org.springframework.beans.factory.support.MethodReplacer
)的逻辑,替换这个方法。通过改变方法执行逻辑来动态改变方法。
parseMetaElements
meta 所声明的 key 并不会在 Bean 中体现,只是一个额外的声明,当我们需要使用里面的信息时,通过调用 BeanDefinition 的
#getAttribute(String name)
方法来获取
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;
//获得key
String key = metaElement.getAttribute(KEY_ATTRIBUTE);
//获得value
String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
//创建BeanMetadataAttribute
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
attribute.setSource(extractSource(metaElement));
//添加到BeanMetadataAttributeAccessor中
attributeAccessor.addMetadataAttribute(attribute);
}
}
}
parseLookupOverrideSubElements
lookup-method :获取器注入,就是把一个只有声明没有实现的bean的逻辑实现通过配置到配置文件中,然后spring将其加载进容器。该方法可以用于设计一些可插拔的功能上,解除程序依赖。
public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
// 遍历子节点
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 标签为lookup-method
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对象
LookupOverride override = new LookupOverride(methodName, beanRef);
override.setSource(extractSource(ele));
overrides.addOverride(override);
}
}
}
parseReplacedMethodSubElements
可以在运行时调用新的方法替换现有的方法,还能动态的更新原有方法的逻辑,动态的进行方法替换
public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 标签为replaced-method
if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
Element replacedMethodEle = (Element) node;
String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);
String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
// 创建 ReplaceOverride 对象
ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
// Look for arg-type match elements.
List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT);
for (Element argTypeEle : argTypeEles) {
// arg-type 子标签
String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE);
// arg-type 子标签的 match 属性
match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
if (StringUtils.hasText(match)) {
replaceOverride.addTypeIdentifier(match);
}
}
replaceOverride.setSource(extractSource(replacedMethodEle));
overrides.addOverride(replaceOverride);
}
}
}