上一小节中,我们最终跟踪到了DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法。在该方法中,进行了两部分的标签解析,一个是默认标签解析,一个是自定义标签解析,本节我们先看默认标签解析,进入到默认标签解析方法:
DefaultBeanDefinitionDocumentReader
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, "import")) {
this.importBeanDefinitionResource(ele);
} else if (delegate.nodeNameEquals(ele, "alias")) {
this.processAliasRegistration(ele);
} else if (delegate.nodeNameEquals(ele, "bean")) {
//处理<bean>标签
this.processBeanDefinition(ele, delegate);
} else if (delegate.nodeNameEquals(ele, "beans")) {
this.doRegisterBeanDefinitions(ele);
}
}
该方法主要是对<import><alias><bean><beans>这几个默认标签进行解析,我们平时用到的最多的是<bean>标签,进入到 this.processBeanDefinition(ele, delegate)记录其具体的实现过程:
DefaultBeanDefinitionDocumentReader
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//1、解析bean标签中的属性,将其封装成bd对象,再将bd对象和beanName、alias封装成BeanDefinitionHolder对象返回
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//2、将BeanDefinitionHolder对象注册到BeanDefinitionMap容器中
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
delegate.parseBeanDefinitionElement(ele)步骤解析
方法中的第一步,delegate.parseBeanDefinitionElement(ele)的作用是解析<bean>标签中的所有属性,将解析出来的标签属性封装成GenericBeanDefinition对象。BeanDefinition对象在Spring容器初始化过程中扮演着极其重要的角色,后面我单独用一个小节来记录BeanDefinition,这里只是简要做一些说明,GenericBeanDefinition对象包含了一个普通的JavaBean经过完整Spring生命周期变成一个SpringBean所需要的所有信息,里面包含了beanClass、scope等关键属性,这里是通过一个代理对象BeanDefinitionParserDelegate进行实际的标签解析,进入该方法:
BeanDefinitionParserDelegate
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//解析bean标签中的id属性
String id = ele.getAttribute("id");
//解析bean标签中的name属性
String nameAttr = ele.getAttribute("name");
List<String> aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
//这里的名称可以使用多个,中间使用",;"分割
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
beanName = (String)aliases.remove(0);
if (this.logger.isTraceEnabled()) {
this.logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
this.checkNameUniqueness(beanName, aliases, ele);
}
//实际解析bean标签属性的方法,并生成BeanDefinition对象
AbstractBeanDefinition beanDefinition = this.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);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (this.logger.isTraceEnabled()) {
this.logger.trace("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
}
} catch (Exception var9) {
this.error(var9.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
//将生成的BeanDefinition对象最终再封装成一个BeanDefinitionHolder对象
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
} else {
return null;
}
}
进入this.parseBeanDefinitionElement(ele, beanName, containingBean),实现如下:
BeanDefinitionParserDelegate
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute("class")) {
//获取bean标签中的class属性
className = ele.getAttribute("class").trim();
}
String parent = null;
//判断bean标签中是否包含parent属性,如果有则解析parent
if (ele.hasAttribute("parent")) {
parent = ele.getAttribute("parent");
}
try {
AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
this.parseMetaElements(ele, bd);
this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
this.parseConstructorArgElements(ele, bd);
this.parsePropertyElements(ele, bd);
this.parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(this.extractSource(ele));
AbstractBeanDefinition var7 = bd;
return var7;
} catch (ClassNotFoundException var13) {
this.error("Bean class [" + className + "] not found", ele, var13);
} catch (NoClassDefFoundError var14) {
this.error("Class that bean class [" + className + "] depends on not found", ele, var14);
} catch (Throwable var15) {
this.error("Unexpected failure during bean definition parsing", ele, var15);
} finally {
this.parseState.pop();
}
return null;
}
方法中的第一步,获取到<bean>标签中的class属性和parent属性(非必须),将获取到的className和parent传入this.createBeanDefinition(className, parent)方法中,返回一个GenericBeanDefinition对象。
BeanDefinitionParserDelegate
protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName) throws ClassNotFoundException {
//通过BeanDefinitionReaderUtils工具类创建BeanDefinition
return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());
}
BeanDefinitionReaderUtils
public static AbstractBeanDefinition createBeanDefinition(@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
//直接new出一个GenericBeanDefinition对象
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;
}
可以看到,方法中就是直接简单粗暴的new出了一个GenericBeanDefinition对象,然后将beanClassName赋值给GenericBeanDefinition中的beanClass属性,但此时的BeanDefinition对象中的属性还都没有赋值,在后面的步骤中会依次将GenericBeanDefinition中的所有属性填充上。
第二步,this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd)方法用于解析bean标签中的所有属性,并填充GenericBeanDefinition对象
BeanDefinitionParserDelegate
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
if (ele.hasAttribute("singleton")) {
//解析singleton属性,最新版本已经去掉
this.error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
} else if (ele.hasAttribute("scope")) {
//解析scope属性,如果不设置,则scope=""
bd.setScope(ele.getAttribute("scope"));
} else if (containingBean != null) {
bd.setScope(containingBean.getScope());
}
//判断bean上是否加了abstract属性
if (ele.hasAttribute("abstract")) {
bd.setAbstract("true".equals(ele.getAttribute("abstract")));
}
//获取bean标签上的lazy-init属性,默认lazyInit="default"
String lazyInit = ele.getAttribute("lazy-init");
if (this.isDefaultValue(lazyInit)) {
//如果lazyInit="default",则lazyInit = "false"
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit("true".equals(lazyInit));
//获取bean的注入模式,默认autowire="default"
String autowire = ele.getAttribute("autowire");
//将注入模式转化为数字类型,依照下面的对应关系:
//byName:1 , byType:2 , constructor:3 , autodetect:4 , default:0
//因此,默认情况下bd.autowireMode="0"
bd.setAutowireMode(this.getAutowireMode(autowire));
String autowireCandidate;
//获取bean标签的depend-on属性,非必须
if (ele.hasAttribute("depends-on")) {
autowireCandidate = ele.getAttribute("depends-on");
bd.setDependsOn(StringUtils.tokenizeToStringArray(autowireCandidate, ",; "));
}
//获取bean标签的autowire-candidate属性,如果没有设置则为默认是"default"
autowireCandidate = ele.getAttribute("autowire-candidate");
String destroyMethodName;
if (this.isDefaultValue(autowireCandidate)) {
destroyMethodName = this.defaults.getAutowireCandidates();
if (destroyMethodName != null) {
String[] patterns = StringUtils.commaDelimitedListToStringArray(destroyMethodName);
bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
}
} else {
bd.setAutowireCandidate("true".equals(autowireCandidate));
}
//获取bean标签的primary属性,非必须
if (ele.hasAttribute("primary")) {
bd.setPrimary("true".equals(ele.getAttribute("primary")));
}
//获取bean标签上的init-method属性,非必须,init-method方法用于springbean完成生命周期后的回调
if (ele.hasAttribute("init-method")) {
destroyMethodName = ele.getAttribute("init-method");
bd.setInitMethodName(destroyMethodName);
} else if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
//获取bean上的destory-method属性
if (ele.hasAttribute("destroy-method")) {
destroyMethodName = ele.getAttribute("destroy-method");
bd.setDestroyMethodName(destroyMethodName);
} else if (this.defaults.getDestroyMethod() != null) {
bd.setDestroyMethodName(this.defaults.getDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
//获取bean上的factory-method属性,该属性的作用是使用指定的工厂方法来实例化一个springbean
if (ele.hasAttribute("factory-method")) {
bd.setFactoryMethodName(ele.getAttribute("factory-method"));
}
//获取bean上的factory-bean属性,该属性的作用是使用指定bean的指定方法来实例化一个bean
if (ele.hasAttribute("factory-bean")) {
bd.setFactoryBeanName(ele.getAttribute("factory-bean"));
}
//这一步完成了bean标签中所有attribute的解析,并存入bd对应的属性中
return bd;
}
第三步,this.parseMetaElements(ele, bd)解析meta信息,这一步省略
第四步,调用this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides())方法,获取<bean>标签下的<lookup-method>子标签,从子标签中获取到bean属性和name属性,封装成一个LookupOverride对象,加入GenericBeanDefinition的MethodOverrides,MethodOverrides中维护了一个Set集合。
BeanDefinitionParserDelegate
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 (this.isCandidateElement(node) && this.nodeNameEquals(node, "lookup-method")) {
Element ele = (Element)node;
String methodName = ele.getAttribute("name");
String beanRef = ele.getAttribute("bean");
//封装成一个LookupOverride对象,LookupOverride类是MethodOverride的子类,他们之间的继承关系:
//public class LookupOverride extends MethodOverride
LookupOverride override = new LookupOverride(methodName, beanRef);
override.setSource(this.extractSource(ele));
//overrides对应bd的methodOverrides,里面保存的是一个set集合
overrides.addOverride(override);
}
}
}
注:<lookup-method>标签的作用是可以在<bean>标签中定义一个抽象类,同时在<lookup-method>子标签的name属性中定义其抽象方法,该抽象方法返回父类对象,然后在bean属性中指定具体要实例化的子类对象,例如:
/**
* 定义一个抽象类
* 其中包含一个抽象方法getVehicle(),返回父类Vehicle对象
*/
public abstract class VehicleService {
public abstract Vehicle getVehicle();
}
定义Vehicle的两个子类,Car和Truck
/*
* 定义一个Car子类继承Vehicle
*/
public class Car extends Vehicle {
public Car(){
System.out.println("This is a Car");
}
}
/*
* 定义一个Truck子类继承Vehicle
*/
public class Truck extends Vehicle {
public Truck(){
System.out.println("This is a Truck");
}
}
在spring.xml文件中加入配置:
<!--定义car实例-->
<bean id="car" class="com.sgcc.uvmp.beans.Car"></bean>
<!--定义truck实例-->
<bean id="truck" class="com.sgcc.uvmp.beans.Truck"></bean>
<!--定义carService class指定为抽象VehicleService类型,在lookup-method标签中定义实际返回的子类为car-->
<bean id="carService" class="com.sgcc.uvmp.beans.VehicleService">
<lookup-method bean="car" name="getVehicle"></lookup-method>
</bean>
<!--定义truckService class指定为抽象VehicleService类型,在lookup-method标签中定义实际返回的子类为truck-->
<bean id="truckService" class="com.sgcc.uvmp.beans.VehicleService">
<lookup-method bean="truck" name="getVehicle"></lookup-method>
</bean>
在方法中进行测试:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//获取carService,调用getVehicle()方法实际得到的是car对象
VehicleService vehicleService = (VehicleService) context.getBean("carService");
vehicleService.getVehicle();
//获取truckService,调用getVehicle()方法实际得到的是truck对象
VehicleService vehicleService2 = (VehicleService) context.getBean("truckService");
vehicleService2.getVehicle();
第五步,调用this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides())方法,解析<replaced-method>标签
BeanDefinitionParserDelegate
public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
//解析<bean>下<replaced-method>子标签
if (this.isCandidateElement(node) && this.nodeNameEquals(node, "replaced-method")) {
Element replacedMethodEle = (Element)node;
//获取到子标签中的name和replacer属性
String name = replacedMethodEle.getAttribute("name");
String callback = replacedMethodEle.getAttribute("replacer");
//封装成一个ReplaceOverride对象,和LookupOverride一样,同时也是继承MethodOverride
ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, "arg-type");
Iterator var11 = argTypeEles.iterator();
while(var11.hasNext()) {
Element argTypeEle = (Element)var11.next();
String match = argTypeEle.getAttribute("match");
match = StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle);
if (StringUtils.hasText(match)) {
replaceOverride.addTypeIdentifier(match);
}
}
replaceOverride.setSource(this.extractSource(replacedMethodEle));
//同样加入到bd.methodOverrides集合中
overrides.addOverride(replaceOverride);
}
}
}
注:<replaced-method>标签的作用是可以替换一个bean中的原有方法,当调用对象原来的方法时,实际调用的是被替换后的方法,例如:
public class PersonService {
//这是替换前的方法
public void printSex(){
System.out.println("This is a Boy");
}
}
/**
* 这是方法替换的类,必须要实现MethodReplacer接口,并实现reimplement方法,在reimplement方法体内部对原方法进行重写
*/
public class MethodReplace implements MethodReplacer {
public Object reimplement(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("This is a Girl");
return null;
}
}
<bean id="methodReplace" class="com.sgcc.uvmp.beans.MethodReplace"></bean>
<bean id="person" class="com.sgcc.uvmp.beans.PersonService">
<!--在这个标签里指定需要重写的方法名,以及替换类的id-->
<replaced-method name="printSex" replacer="methodReplace"></replaced-method>
</bean>
PersonService personService = context.getBean(PersonService.class);
//获取personService实例,然后调用printSex()方法,但实际调用的是MethodReplace类中的逻辑
//方法实现被替换了
personService.printSex();
第六步,调用this.parseConstructorArgElements(ele, bd)方法,解析<constructor-arg>子标签,并存入bd的ConstructorArgumentValues属性,比较简单,这里忽略。
第七步,调用this.parsePropertyElements(ele, bd)方法,解析<property>子标签,并存入bd的MutablePropertyValues属性。MutablePropertyValues类内部维护了一个List<PropertyValue>类型的集合,可以保存多个<property>子标签的值。
private final List<PropertyValue> propertyValueList;
第八步,调用this.parseQualifierElements(ele, bd)方法,解析<qualifier>子标签,并存如bd的qualifiers属性,这里不常用,我就先不记录了。
至此,this.parseBeanDefinitionElement(ele, beanName, containingBean)方法调用完成,bd中的属性都已经填充完毕,后面又将bd封装成了一个BeanDefinitionHolder对象,对象中包含了bd的实例,beanName以及aliases别名,将此对象返回。这一步操作的目的,我认为只是为了方便后面获取beanName以及通过beanName获取对应的bd实例。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry())方法解析
将上面步骤中封装成的BeanDefinitionHolder对象及BeanDefinitionRegistry对象传入该方法中,将bd对象加入到bd容器中,具体看方法实现
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
//这一步从BeanDefinitionHolder对象中取出beanName对应的bd对象,加入到BeanDefinitionRegistry注册器中
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}
}
该方法涉及到BeanDefinition体系中非常重要的一个类BeanDefinitionRegistry,可以认为这是BeanDefinition的注册器,里面注册了Spring容器启动过程中所有的BeanDefinition对象,它是一个接口,我们的Spring容器在一开始会创建一个DefaultListableBeanFactory对象,这就是常说的Bean工厂,里面维护了所有生成的Bean实例,我们常用的通过ApplicationContext.getBean()来获取Bean,其实就是从这个Bean工厂中获取的,DefaultListableBeanFactory这个类本身就实现了BeanDefinitionRegistry,说白了Spring初始化容器时加载的所有BeanDefinition对象也都维护在这个Bean工厂类中,来记录一下类的集成关系。
/**
* DefaultListableBeanFactory实现了BeanDefinitionRegistry接口
*/
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable
接下来一个重要的方法就是registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()),这个方法的作用应该就是将bd对象加入到容器中,进入方法看实现
DefaultListableBeanFactory
/**
* 该方法核心的作用就是将beanName加入到beanDefinitionNames中,同时把beanName和bd对象的映射关系加入到beanDefinitionMap集合中
*/
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var8) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
}
}
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
if (existingDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(existingDefinition)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if (this.hasBeanCreationStarted()) {
Map var4 = this.beanDefinitionMap;
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
this.removeManualSingletonName(beanName);
}
} else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition == null && !this.containsSingleton(beanName)) {
if (this.isConfigurationFrozen()) {
this.clearByTypeCache();
}
} else {
this.resetBeanDefinition(beanName);
}
}
这个方法中,涉及到两个重要的集合对象,beanDefinitionNames和beanDefinitionMap,beanDefinitionNames是ArrayList类型,用于存放所有的beanName,beanDefinitionMap是ConcurrentHashMap类型,用于存放所有的beanName和bd对象的映射关系,在后面做bean实例化时,还会用到这两个集合,这里我们先记下来,在后面的记录中我们还会看到这两个对象。
到此为止,bean标签的解析过程完成。总结起来,一个bean标签的解析过程首先是从xml配置文件中将<bean>标签中的属性(Attribute)解析出来,然后将子标签中的属性解析出来,将解析出来的所有属性都对应赋值到一个Beandefinition对象的属性中,完成bd对象的封装,最终将该bd对象注册到BeanDefinitionRegistry容器中维护的beanDefinitionMap和beanDefinitionNames两个集合中,完成收集。