内容接上一篇文章 Spring源代码之bean的基本解析,讲到了默认标签的解析,这里接上内容:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
//获得beans节点的子节点
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//如果子节点的element
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);
}
}
直说默认标签的解析parseDefaultElement(ele, delegate),进入方法:
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标签的解析,如果是beans,会继续解析里面的标签(一般就是bean),那么还会回来到这个方法,这块其实是一个循环引用
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
先看bean标签的解析,其实,基本上所有的标签属性等都在BeanDefinitionParserDelegate这里声明了,看到这里会有一些激动,因为这是一个单独的类,终于没有继承,实现别的类活接口了!先看bean标签的解析,这块儿没有结构性的复杂,但是逻辑上跟复杂!
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//调用BeanDefinitionParserDelegate类的(ele)方法解析,这里会得到一些属性
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
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));
}
}
delegate.parseBeanDefinitionElement(ele);进入这个方法里:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
//获得标签的id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
//获得标签name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
//如果有name属性,分割name属性,以","或者";"
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
//声明beanName并把id赋值给他
String beanName = id;
//如果beanName为空,并且aliases不是空,上面nameArr分割的第一个值赋值给beanName,并且删除
//如果beanName也就是ID为null其实这里不抛,后面也会跑异常的
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
//参数containingBean传过来的就是null
if (containingBean == null) {
//检查唯一性
checkNameUniqueness(beanName, aliases, ele);
}
//上面代码是处理bean标签的id,name属性,到这个方法里,就是其他属性了,这里面也很多
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
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.isDebugEnabled()) {
logger.debug("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;
}
上部分代码片里的parseBeanDefinitionElement(ele, beanName, containingBean);方法:
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
//获得class属性的内容
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
//获得parent属性
try {
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
//创建AbstractBeanDefinition,这个类的用处是装这些属性,实际上是GenericBeanDefinition也就是他的子类
//这个方法点进去会有bd.setBeanClass(ClassUtils.forName(className, classLoader))这样一行代码
//这个代码就是用同意虚拟机下的类加载器,来生成bean的类
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//解析各种其他属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//获得description,并放入创建AbstractBeanDefinition
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//获得元数据
parseMetaElements(ele, bd);
//获得lookup-method"
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//获得replaced-method属性
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//获得构造函数
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;
}
这块儿代码的核心就是返回一个AbstractBeanDefinition类型的数据,其实这个就是装在bean各种属性的一个容器.继续往里面看,他返回的是GenericBeanDefinition,他是AbstractBeanDefinition的子类.经过一层层的调用,我贴出的代码片,也就是processBeanDefinition方法里,会有一个BeanDefinitionHolder,就是这来的,只不过GenericBeanDefinition是放入BeanDefinitionHolder,又多了一层容器,那么逻辑关系也就是GenericBeanDefinition继承了AbstractBeanDefinition,而BeanDefinitionHolder才是他们的容器!
说到了BeanDefinition,上面只提到了GenericBeanDefinition,其实还有另外两种BeanDefinition,他们都实现了BeanDefinition接口并继承了AbstractBeanDefinition.
下面层级的代码,不想往这贴了,太多了,但是我都加了注释,或者正在家注释,这是一个工作量很大的事儿,没有太多的技术含量,需要的只是一点点看,所以想看的话可以去spring源代码中文注释这里看!
写到这里,其实可以顺着这个思路来细看了,脉络已经出来了,其实这里面很关键的就是AbstractBeanDefinition,说白了,bean的解析过程,无非就是将xml内容,转移到这个类中,那么梳理一下这个类的各种属性:
//删除了常亮等
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
//classLoader生成的bean实例
private volatile Object beanClass;
//bean的作用范围
private String scope = SCOPE_DEFAULT;
//是否是抽象
private boolean abstractFlag = false;
//是否懒加载
private boolean lazyInit = false;
//自动注入模式,对应bean的属性autowire
private int autowireMode = AUTOWIRE_NO;
//依赖检查
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
//一个bean实例化,依赖的别的bean
private String[] dependsOn;
//查找自动装配对象
private boolean autowireCandidate = true;
//自动装备时候,多个bean是否是首选
private boolean primary = false;
//记录qualifier
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(0);
//这个有待研究
private Supplier<?> instanceSupplier;
//允许访问飞公开的构造器
private boolean nonPublicAccessAllowed = true;
//宽松模式解析构造器
private boolean lenientConstructorResolution = true;
//属性factory-bean
private String factoryBeanName;
//属性factory-method
private String factoryMethodName;
//构造器值
private ConstructorArgumentValues constructorArgumentValues;
//属性集合
private MutablePropertyValues propertyValues;
//方法重写的持有者
private MethodOverrides methodOverrides = new MethodOverrides();
//属性init-method
private String initMethodName;
//destroy-method
private String destroyMethodName;
//是否执行initMethodName
private boolean enforceInitMethod = true;
//是否执行destroy-method
private boolean enforceDestroyMethod = true;
//创建aop时候为true
private boolean synthetic = false;
private int role = BeanDefinition.ROLE_APPLICATION;
//描述信息
private String description;
//bean定义的资源
private Resource resource;
说到这里,挖掘出这个抽象类,其实解析这里已经差不多了,至于其他的详细解析,太多了,没法往这上面贴,还有就是自定义标签没打算说,还有就是开始数第三个代码片中的bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);这个也没打算说,这个是默认标签下的自定义属性(标签)解析,所以也不说了,不知道的可以去查一下怎么去自定义属性(标签),下一篇文章会是bean的加载!