1.简介
Spring的启动分为关键步骤,首先是将配置文件中定义的<bean>信息加载到BeanDefintionRegistry中。然后通过BeanFactory中的getBean方法来将BeanDefinition进行实例化,开始整个bean的生命周期。
2.BeanDefinitionReader
public interface BeanDefinitionReader {
BeanDefinitionRegistry getRegistry();//获取到对应的BeanDefinitionRegistry
ResourceLoader getResourceLoader();//获取到ResourceLoader,为了获取对应的Resource,可以认为是一个工厂方法。
ClassLoader getBeanClassLoader();//获取ClassLoader
BeanNameGenerator getBeanNameGenerator();//获取到BeanName的命名
int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;//将Resource中的Bean加载到BeanRegistry中来。
int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;//将localtions对应的文件中定义的BeanDefinition加载并注册到BeanRegistry中来。
int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;
}
BeanDefinitionReader依赖了ResourceLoader,BeanDefinitionRegistry,Resource这些关键类。从接口看来loadBeanDefintions()方法,主要是将Resource中定义的Bean对象加载到BeanDefinitionRegistry中来。
3.BeanDefinition的加载过程
4.关键代码阅读
4.1 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException
当前方法首先是对resource中定义的Document进行加载,校验,解析为一个Document对象。然后通过registerBeanDefinitions(doc,resource)将当前Document中的bean加载到BeanDefinitionRegistry中来。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);//这个过程当中主要是对当前的xml文件进行解析,校验,获取到对应的Document的对象。
return registerBeanDefinitions(doc, resource);//这个方法是关键
}
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);
}
}
4.2registerBeanDefinitions(doc, resource)
主要是讲doc中定义的<bean>等相关的信息加载到BeanDefinitionRegistry。
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();//第一步创建BeanDefinitionDocumentReader。这个是一个BeanDefinition的从Document读取的Reader。
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//通过BeanDefinitionDocumentReader的registerBeanDefinitions(doc, createReaderContext(resource))方法将Document中定义的Bean注册到registry中去。
return getRegistry().getBeanDefinitionCount() - countBefore;
}
当前方法将加载的任务委托给了 BeanDefinitionDocumentReader中的registerBeanDefinitions(doc, createReaderContext(resource))方法。
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
4.3BeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)
看下如何实现的:
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);//创建BeanDefinitionParseDelegate,其中对于lazy-init。auto-wire中相关的全局的默认的设置。
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
4.4 parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
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)) {
parseDefaultElement(ele, delegate);//这个是Spring中定义的Element的实现。
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);//用户自定义的Element类型。这里先按下不表。
}
}
以上方法,对于xml中定义的有Spring中默认定义的标签,也有用户自定义的标签。这里重点看下Spring自定义的标签。
4.5 parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
看下是如何注册 系统中定义的Element的。这里是如何将Element转变为BeanRegistry中定义的BeanDefinition或者是其他相关的辅助内容的?这里是关键。
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {//处理import文件。
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {//这里是 alias处理的别名
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {//这里是<bean>,这个是重点关注的。
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {//这个是嵌套的<beans>.
// recurse
doRegisterBeanDefinitions(ele);
}
}
这里重点看下是如何解析<bean> 的。
4.6 processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);//这里是讲一个element转变为一个BeanDefinitionHolder、
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);//BeanDefinition的额外的解析工作。
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());//将BeanDefinitionHolder注册到BeanDefinitionRegistry中去。
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));//发布一下创建的成功的事件。
}
}
从上面的代码可见,将一个<bean>转变为注册为注册在BeanDefinitionRegitry中的GenericBeanDefinition主要有以上的几个步骤:
第一步:通过 parseBeanDefinitionElement(ele) 将当前的<bean>转变为一个BeanDefinitionHolder。其中包括了 beanName,aliasName和GenericBeanDefinition。
第二步:通过decorateBeanDefinitionIfRequired(ele, bdHolder)方法对于BeanDefinitionHolder进行额外的处理,主要是对于<bean>中用户自定义的一些标签。
第三步:通过BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())将当前的BeanDefinitionHolder对象注册到目标BeanDefinitionRegistry中去。
第四步:将注册完成的事件发布一下事件。
4.6.1 parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)
看下public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) 方法,是调用了BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)。
看下具体实现,由于<bean>配置比较的复制,可能会有省略。
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<String>();
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 = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
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;
}
4.6.1.1 确定beanName
确定当前的beanName和alias:首先是beanName = id。alias = name中以“,;”分割的字符串。如果id为空,就一alias种第一个为beanName,剩余的为alias。
4.6.1.2 判断bean是否唯一
判断beanName是否被使用过。如果使用过就报错,这里对于错误的处理是值得看下的:
protected void error(String message, Element source) {
this.readerContext.error(message, source, this.parseState.snapshot());
}
在当前的类中有一个统一的error的方法,然后想对于异常信息的处理交给ReaderContext的error()去统一处理。这样相对比较的灵活,如果是直接抛出异常反而没有这种方式好。当然error方法最终一定要打断当前的执行进程的。
4.6.1.3 开始解析 BeanDefinition对象
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean)。
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {//开始处理class标签
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;//看下有没有parenet的实现。
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
AbstractBeanDefinition bd = createBeanDefinition(className, parent);//创建GenericBeanDefinition对象,主要设置parentClassName和ClassName。如果指定了ClassLoader,就将当前的class进行加载进来。
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);//解析BeanDefinition中Attribute、
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));//设置一下description的实现。
parseMetaElements(ele, bd);//meta属性Element
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
parseConstructorArgElements(ele, bd);
parsePropertyElements(ele, bd);
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;
}
看一下 在<bean>中定义的Attribute是如何解析的。这些都是定义在<bean>中的attribute,这些并不太复杂。
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
BeanDefinition containingBean, AbstractBeanDefinition bd) {
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {//如果属性中有sigleton,这个时候就报错。
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) {//如果containBean不为空,就设置对象的scope为最新的scope。
// Take default from containing bean in case of an inner bean definition.
bd.setScope(containingBean.getScope());
}
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {//设置当前对象为abstract对象。
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);//设置lazy-init属性。
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);//设置自动装配属性。 bd.setAutowireMode(getAutowireMode(autowire));
String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);//设置 依赖自动检查
bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {//设置依赖属性
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
}
//设置 Autowire_Candidate_attribure属性,如果这个属性设置为false,这个对象将不会作为被自动装配的对象。
//首先会使用全局的autowire_candidate_attribute的属性,然后看当前<bean>中的设置,当前<bean>中设置的优先级更高。
String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(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属性的将会被优先的选中,否者就会抛出异常。也可以使用 Qualifier这个属性来帮助解决多个候选者的问题。
if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
}
//init-method 这个方法是Spring的生命周期中的一个方法。
//在bean中设置的init-method方法的优先级比全局的优先级高。
if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
if (!"".equals(initMethodName)) {
bd.setInitMethodName(initMethodName);
}
}
else {
if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
}
//bean对象被销毁是将会调用的方法,和init方法一样,<bean>中定义的优先级高于 全局定义的destory方法。
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);
}
}
//这两个属性是在Spring中使用工厂方来进行管理,其中一个是factory-bean,一个是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;
}
解析完attribute后,开始解析 meta属性了。
<bean id="zandan" class="com.test.bean.meta.MetaDataBean">
<meta key="metaData" value="testMataData"/>
</bean>
看下是如何解析的:
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)) {//如果当前的Node是Spring自定义的,同时== meta数据
Element metaElement = (Element) node;
String key = metaElement.getAttribute(KEY_ATTRIBUTE);
String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);//创建一个BeanMetaDataAttribute的属性。
attribute.setSource(extractSource(metaElement));
attributeAccessor.addMetadataAttribute(attribute);//将属性添加到AttributeAccessor中去。其中BeanMetadataAttributeAccessor是GenericBeanDefinition的属性。
}
}
}
其中meta数据转变为一个BeanMetadataAttribute中去。
lookup属性的解析:
<bean id="testLookUp" class="com.test.bean.lookUp.GetBeanTest" >
<lookup-method name="getUser" bean="student"/>
</bean>
<bean id="student" class="com.test.bean.lookUp.Teacher"/>
其中在GetBeanTest中定义了一个Abstract的方法,这个方法返回一个User类型的对象。
然后在Spring的配置文件中定义一个<lookup-method name="getUser" bean = "student">其中 bean=“student”中定义的是User类型的子类。
首先看下解析过程,将<bean>定义的look-up相关内容转变为GenericBeanDefinition中的信息中的LookupOverride的内容。
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)) {//这个属性是LookUp方法。
Element ele = (Element) node;
String methodName = ele.getAttribute(NAME_ATTRIBUTE);
String beanRef = ele.getAttribute(BEAN_ELEMENT);
LookupOverride override = new LookupOverride(methodName, beanRef);//LookupOverride,这个方法是MethodOverride的子类。
override.setSource(extractSource(ele));
overrides.addOverride(override);//将当前的LookupOverride添加到当前系统中去。
}
}
}
repleace-method的解析:
看下配置文件中的内容:
<bean id="testChangeMethod" class="com.test.bean.replace.TestChangeMethod">
<replaced-method name="changeMe" replacer="replacer"/>
</bean>
<bean id="replacer" class="com.test.bean.replace.TestMethodReplacer"/>
代码的实现:
public class TestChangeMethod {
public void changeMe() {
System.out.println("changeMe");
}
}
public class TestMethodReplacer implements MethodReplacer {
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
System.out.println("我替换了原有的方法");
return null;
}
}
replace-method主要是替换当前系统中的某一个方法.其中替换方法需要实现MethodReplacer的接口。
解析的过程中,最后是将replaceMethod的定义解析为 ReplaceOverride,然后添加到BeanDefinition中的Overrides中去。
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)) {//判断当前对象是replce-method标签。
Element replacedMethodEle = (Element) node;
String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);//获取被替换的方法。
String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);//获取替换的bean
ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);//创建一个替换的Override的bean,这个bean被定义为callback方法。
// Look for arg-type match elements.
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);//将overridede方法添加到GenericBeanDefinition中去。
}
}
}
构造函数的解析:
通过构造函数来构造一个Bean。其中的过程如下:
<bean id="helloBean" class="com.test.bean.construct.HelloBean">
<constructor-arg index="0">
<value>张三</value>
</constructor-arg>
<constructor-arg index="1">
<value>你好吗?</value>
</constructor-arg>
</bean>
HelloBen的代码如下:
public class HelloBean {
private String name;
private String say;
public HelloBean(String name, String say) {
this.name = name;
this.say = say;
}
public void sayHello() {
System.out.println(name + " : " + say);
}
}
看下解析Bean的Constructor中信息的过程:
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)) {//获取到constructor-arg的属性。
parseConstructorArgElement((Element) node, bd);//这个是关键
}
}
}
具体的实现:
public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);//根据Index来调用Constructor的Bean。
String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);//根据Type来调用Constructor的Bean。
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);//根据Name来调用Constructor的Bean。
if (StringUtils.hasLength(indexAttr)) {//其中index是最优先进行实例化的。
try {
int index = Integer.parseInt(indexAttr);
if (index < 0) {
error("'index' cannot be lower than 0", ele);
}
else {
try {
this.parseState.push(new ConstructorArgumentEntry(index));
Object value = parsePropertyValue(ele, bd, null);//解析当前element中的value值。
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);//构造ConstructorArgumentValue属性。
if (StringUtils.hasLength(typeAttr)) {//设置Type属性
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {//设置Name属性
valueHolder.setName(nameAttr);
}
valueHolder.setSource(extractSource(ele));//设置source。
if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {//判断当前的Index是否设置过了,如果有过,就报错。
error("Ambiguous constructor-arg entries for index " + index, ele);
}
else {
bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);//将当前的ConstructorArgumentValue写到GenericBeanDefinition中去。其中写入的是IndexArgumentValue.在实例化的时候,index的优先级也会比当前的对象高。
}
}
finally {
this.parseState.pop();
}
}
}
catch (NumberFormatException ex) {
error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
}
}
else {
try {
this.parseState.push(new ConstructorArgumentEntry());
Object value = parsePropertyValue(ele, bd, null);//解析属性
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
if (StringUtils.hasLength(typeAttr)) {
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
valueHolder.setName(nameAttr);
}
valueHolder.setSource(extractSource(ele));
bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);//将当前的type和和name相关的 GenericArgumentValue写入到当前BeanDefinition中去。
}
finally {
this.parseState.pop();
}
}
}
Spring中属性的设置主要有三种方式,其中是 在 attribute中 设置ref。一种是在attribute中设置value。还有一种是 在Property设置 子element 的属性。
//获取property element中的 value。可能是list属性。
//也有可能使用在constructor 属性中 propertyName可能为 null。
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
String elementName = (propertyName != null) ?
"<property> element for property '" + propertyName + "'" :
"<constructor-arg> element";//如果propertyName 为null的时候,elementName = constructor-arg。
// Should only have one child element: ref, value, list, etc.//当前属性中应该只有一个子Element。
NodeList nl = ele.getChildNodes();//所有的子Node属性。
Element subElement = null;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
!nodeNameEquals(node, META_ELEMENT)) {
// Child element is what we're looking for.
if (subElement != null) {
error(elementName + " must not contain more than one sub-element", ele);
}
else {
subElement = (Element) node;
}
}
}
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);//当前的Property中是否有ref属性
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);//当前Property中是否有value属性。
if ((hasRefAttribute && hasValueAttribute) ||
((hasRefAttribute || hasValueAttribute) && subElement != null)) {// 如果当前Property中已经有了ref或者是value,这个时候就需要报错,因为已经重复了。
error(elementName +
" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
if (hasRefAttribute) {//如果是在attribute中设置的ref。
String refName = ele.getAttribute(REF_ATTRIBUTE);//获取到 ref对应的beanName。
if (!StringUtils.hasText(refName)) {
error(elementName + " contains empty 'ref' attribute", ele);
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName);//构造RuntimeBeanReference。
ref.setSource(extractSource(ele));
return ref;//返回结果。
}
else if (hasValueAttribute) {
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
valueHolder.setSource(extractSource(ele));
return valueHolder;//返回TypeStringValue的值。
}
else if (subElement != null) {
return parsePropertySubElement(subElement, bd);//返回解析SubElement的值。
}
else {
// Neither child element nor "ref" or "value" attribute found.。如果 ref Attribute ,Value Attribute 以及 sub Element都为空的时候,这个时候就报错。
error(elementName + " must specify a ref or value", ele);
return null;
}
}
下面看下 public Object parsePropertySubElement(Element ele, BeanDefinition bd)
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
if (!isDefaultNamespace(ele)) {//如果当前的属性是用户自定义的Bean信息,调用解析用户自定义的属性。
return parseNestedCustomElement(ele, bd);
}
else if (nodeNameEquals(ele, BEAN_ELEMENT)) { //如果Element是一个bean的时候。
BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);//对当前的Bean进行解析。这个就是一个解析正常的Bean的过程。
if (nestedBd != null) {
nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);//对当前的Bean进行装饰
}
return nestedBd;//返回解析的Bean。
}
else if (nodeNameEquals(ele, REF_ELEMENT)) { //如果Property中是ref类型的子Element
//如果当前的Node是ref类型的。,主要包括 bean , ref 和 parent三种类型。对于这三种类型的实现。如果这三种 refName都为空的时候就报错误
// A generic reference to any name of any bean.
String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);//取出对应的Bean 的Name信息。
boolean toParent = false;
if (!StringUtils.hasLength(refName)) {//如果BeanName为空,这个时候就使用 local-ref
// A reference to the id of another bean in the same XML file.
refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);//将local-ref设置给 refName
if (!StringUtils.hasLength(refName)) {
// A reference to the id of another bean in a parent context.
refName = ele.getAttribute(PARENT_REF_ATTRIBUTE); //如果localRef为null,这个时候需要将 parenet值设置为 refName.同时将
toParent = true;
if (!StringUtils.hasLength(refName)) {
error("'bean', 'local' or 'parent' is required for <ref> element", ele);
return null;
}
}
}
if (!StringUtils.hasText(refName)) {
error("<ref> element contains empty target attribute", ele);
return null;
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);//根据获取到的ref信息来构造一下RuntimeReference。
ref.setSource(extractSource(ele));
return ref;
}
else if (nodeNameEquals(ele, IDREF_ELEMENT)) {//idRef解析,idRef主要用来注入一个bean的Id,注入的其实还是 一个 String的信息。
return parseIdRefElement(ele);
}
else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
return parseValueElement(ele, defaultValueType);
}
else if (nodeNameEquals(ele, NULL_ELEMENT)) {
// It's a distinguished null value. Let's wrap it in a TypedStringValue
// object in order to preserve the source location.
TypedStringValue nullHolder = new TypedStringValue(null);
nullHolder.setSource(extractSource(ele));
return nullHolder;
}
else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
return parseArrayElement(ele, bd);
}
else if (nodeNameEquals(ele, LIST_ELEMENT)) {
return parseListElement(ele, bd);
}
else if (nodeNameEquals(ele, SET_ELEMENT)) {
return parseSetElement(ele, bd);
}
else if (nodeNameEquals(ele, MAP_ELEMENT)) {
return parseMapElement(ele, bd);
}
else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
return parsePropsElement(ele);
}
else {
error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
return null;
}
}
看一下是如何解析 IdRef的Element的。其中返回的结果是一个RuntimeBeanNameReference的属性。
<! -- idref 主要通过 bean 和local两种方式来指定 -->
<idref bean="subClass"></idref>
<idref local="subClass"></idref>
public Object parseIdRefElement(Element ele) {
// A generic reference to any name of any bean.
String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);//获取到beanName。
if (!StringUtils.hasLength(refName)) {//如果BeanName为空
// A reference to the id of another bean in the same XML file.
refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);//获取到localRef的信息
if (!StringUtils.hasLength(refName)) {
error("Either 'bean' or 'local' is required for <idref> element", ele);
return null;
}
}
if (!StringUtils.hasText(refName)) { //如果这两种方式都没有对应的ref的信息,这个时候就报错。
error("<idref> element contains empty target attribute", ele);
return null;
}
RuntimeBeanNameReference ref = new RuntimeBeanNameReference(refName);
ref.setSource(extractSource(ele));
return ref;
}
看一下 Value值是如何进行处理的: 返回的结果是一个 TypeStringValue
使用value值是这样设置的:
<property name="beanName" >
<value type="java.lang.String">zhagnsan</value>
</property>
看下代码的实现:
/**
* Return a typed String value Object for the given value element.
*/
public Object parseValueElement(Element ele, String defaultTypeName) {
// It's a literal value.
String value = DomUtils.getTextValue(ele);//获取到其中的值
String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE);//获取value对应的属性Type String typeName = specifiedTypeName;
if (!StringUtils.hasText(typeName)) {
typeName = defaultTypeName;//设置默认的 typeName。
}
try {
TypedStringValue typedValue = buildTypedStringValue(value, typeName);//构造 TypeStringValue的值,这个过程主要是将当前的对象添加到系统中。
typedValue.setSource(extractSource(ele));
typedValue.setSpecifiedTypeName(specifiedTypeName);
return typedValue;
}
catch (ClassNotFoundException ex) {
error("Type class [" + typeName + "] not found for <value> element", ele, ex);
return value;
}
}
看一下是如何设置 Array 的属性值的:这个array是一个数组。
<property name="reds">
<array value-type="java.lang.Integer">
<value>12</value>
<value>23</value>
<value>33</value>
</array>
</property>
看一下解析的代码,解析后返回一个ManagedArray对象。
public Object parseArrayElement(Element arrayEle, BeanDefinition bd) {
String elementType = arrayEle.getAttribute(VALUE_TYPE_ATTRIBUTE);//获取value-type的属性。
NodeList nl = arrayEle.getChildNodes();//获取所有的属性
ManagedArray target = new ManagedArray(elementType, nl.getLength());//创建一个MannagedArray
target.setSource(extractSource(arrayEle));//设置source。
target.setElementTypeName(elementType);//设置一下elementType的值
target.setMergeEnabled(parseMergeAttribute(arrayEle));//设置一下当前对象中的 是否能够进行merge。
parseCollectionElements(nl, target, bd, elementType);//其中对当中的一个nodeList进行解析,这个过程主要是一个循环的解析 sub Element。
return target;
}
List的解析和Array的解析相类似。
Set的解析也想类似,主要是是 返回的结果中的ManagedSet中继承的是一个HashSet,而List中依赖的是一个List。
看下Map的解析过程,返回的结果是一个ManageMap的实现。
<property name="map">
<map key-type="java.lang.String" value-type="java.lang.String">
<entry key="lisi">
<value>lisi</value>
</entry>
<entry key="wangwu">
<value>wangwu</value>
</entry>
</map>
</property>
/**
* Parse a map element.
*/
public Map<Object, Object> parseMapElement(Element mapEle, BeanDefinition bd) {
String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE);// 关键的key的类型值
String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE);// value 的类型值
List<Element> entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT);//获取到所有的Entry中的值
ManagedMap<Object, Object> map = new ManagedMap<Object, Object>(entryEles.size());//创建一个MangedMap的值
map.setSource(extractSource(mapEle));//设置 source
map.setKeyTypeName(defaultKeyType);//设置 keyType的值
map.setValueTypeName(defaultValueType);//设置value的Type值
map.setMergeEnabled(parseMergeAttribute(mapEle));//解析元素的合并元素
for (Element entryEle : entryEles) {//对当前的EntryElement进行分别的解析。
// Should only have one value child element: ref, value, list, etc.
// Optionally, there might be a key child element.
NodeList entrySubNodes = entryEle.getChildNodes();//获取到NodeList。其中每一个Node代表的是一个entry。
Element keyEle = null; //key值
Element valueEle = null;//value值
for (int j = 0; j < entrySubNodes.getLength(); j++) {
Node node = entrySubNodes.item(j);
if (node instanceof Element) {
Element candidateEle = (Element) node;
if (nodeNameEquals(candidateEle, KEY_ELEMENT)) {
if (keyEle != null) {
error("<entry> element is only allowed to contain one <key> sub-element", entryEle);
}
else {
keyEle = candidateEle;
}
}
else {
// Child element is what we're looking for.
if (nodeNameEquals(candidateEle, DESCRIPTION_ELEMENT)) {
// the element is a <description> -> ignore it
}
else if (valueEle != null) {
error("<entry> element must not contain more than one value sub-element", entryEle);
}
else {
valueEle = candidateEle;
}
}
}
}
// Extract key from attribute or sub-element.
//提取Key值:key值有三种情况,第一种是 TypedStringValue。第二种是 RuntimeBeanReference。第三种可能是一个subElement对应的对象。
Object key = null;
boolean hasKeyAttribute = entryEle.hasAttribute(KEY_ATTRIBUTE);//查看下当前的实现是否包含了 key值
boolean hasKeyRefAttribute = entryEle.hasAttribute(KEY_REF_ATTRIBUTE);//看下是否包含了keyref
if ((hasKeyAttribute && hasKeyRefAttribute) ||
((hasKeyAttribute || hasKeyRefAttribute)) && keyEle != null) {//key的值不能为同时为空
error("<entry> element is only allowed to contain either " +
"a 'key' attribute OR a 'key-ref' attribute OR a <key> sub-element", entryEle);
}
if (hasKeyAttribute) {//如果key值不为空,这个时候,key为一个 TypeStringValue的值。
key = buildTypedStringValueForMap(entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyType, entryEle);
}
else if (hasKeyRefAttribute) {//如果keyRefAttribute不为null,这个时候需要完成的工作是创建一个RuntimeBeanReference的对象。
String refName = entryEle.getAttribute(KEY_REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error("<entry> element contains empty 'key-ref' attribute", entryEle);
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(extractSource(entryEle));
key = ref;
}
else if (keyEle != null) {
key = parseKeyElement(keyEle, bd, defaultKeyType);//获取到key的value值。
}
else {
error("<entry> element must specify a key", entryEle);
}
// 从Value提取对应的值。其中关键的是
Object value = null;
boolean hasValueAttribute = entryEle.hasAttribute(VALUE_ATTRIBUTE);
boolean hasValueRefAttribute = entryEle.hasAttribute(VALUE_REF_ATTRIBUTE);
boolean hasValueTypeAttribute = entryEle.hasAttribute(VALUE_TYPE_ATTRIBUTE);
if ((hasValueAttribute && hasValueRefAttribute) ||
((hasValueAttribute || hasValueRefAttribute)) && valueEle != null) {
error("<entry> element is only allowed to contain either " +
"'value' attribute OR 'value-ref' attribute OR <value> sub-element", entryEle);
}
if ((hasValueTypeAttribute && hasValueRefAttribute) ||
(hasValueTypeAttribute && !hasValueAttribute) ||
(hasValueTypeAttribute && valueEle != null)) {
error("<entry> element is only allowed to contain a 'value-type' " +
"attribute when it has a 'value' attribute", entryEle);
}
if (hasValueAttribute) {
String valueType = entryEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
if (!StringUtils.hasText(valueType)) {
valueType = defaultValueType;
}
value = buildTypedStringValueForMap(entryEle.getAttribute(VALUE_ATTRIBUTE), valueType, entryEle);
}
else if (hasValueRefAttribute) {
String refName = entryEle.getAttribute(VALUE_REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error("<entry> element contains empty 'value-ref' attribute", entryEle);
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(extractSource(entryEle));
value = ref;
}
else if (valueEle != null) {
value = parsePropertySubElement(valueEle, bd, defaultValueType);
}
else {
error("<entry> element must specify a value", entryEle);
}
// Add final key and value to the Map.
map.put(key, value);//将结果添加到一个 ManagedMap<Object,Object>当中去。
}
return map;
}
Map解析起来比较的复杂,主要是map中的key和value都可能是 value,ref,其他的subElement。这三种定义返回的结果都不一样,分别返回TypeStringValue,RuntimeBeanRegerence以及调用parseSubElement返回的结果。
下面看下 解析Qualifier 当中的属性元素:
Qualifier:主要解决的问题是按照类型进行注入的时候,当同一个类型找到了多个bean的时候,这个时候会发生歧义,会报错。这个时候使用Qualifer来指定其中一个值。解析结果是一个AutowireCandidateQualifier对象:
<bean id="helloBean" class="com.test.bean.construct.HelloBean">
<qualifier type="" value=""/>
</bean>
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);//解析 Qualifier的实现。
}
}
}
public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
String typeName = ele.getAttribute(TYPE_ATTRIBUTE); //注入的Type类型的名称、
if (!StringUtils.hasLength(typeName)) {//如果类型名称为空,这个时候就报错。
error("Tag 'qualifier' must have a 'type' attribute", ele);
return;
}
this.parseState.push(new QualifierEntry(typeName));
try {
AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);//创建一个AutowireCandidateQualifier对象其中有了所有的待注入的内容对象的类型。
qualifier.setSource(extractSource(ele));//设置source的值
String value = ele.getAttribute(VALUE_ATTRIBUTE);//找到对应的value值
if (StringUtils.hasLength(value)) {//如果确实设置了value值
qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
}
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {//在设置底层的对象。
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) {
Element attributeEle = (Element) node;
String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE);
String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE);
if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) {
BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
attribute.setSource(extractSource(attributeEle));
qualifier.addMetadataAttribute(attribute);
}
else {
error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
return;
}
}
}
bd.addQualifier(qualifier);
}
finally {
this.parseState.pop();
}
}
以上为解析<bean>为一个GenericBeanDefinition的关键步骤。
4.6.1.4如果当前的beanName为空,就为这个对象生成一个默认的beanName。
生成默认的BeanName的算法 看下:
首先使用生成的Bean的Class的name。然后如果为空,就使用 parenetName+"$child"。接着还为空,就使用 factoryBeanName+"$created".最后还是为空,这个时候就报错。
然后需要处理一下重复的内容,如果是innerClass,这个时候,需要完成的功能是 id = id+"#"+hashCode. 如果这个对象当中已经有了额外的对象。这个时候可以使用 id= id+counter
看下代码:
public static String generateBeanName(
BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
throws BeanDefinitionStoreException {
String generatedBeanName = definition.getBeanClassName();//获取到当期那bean对应的ClassName
if (generatedBeanName == null) {
if (definition.getParentName() != null) {
generatedBeanName = definition.getParentName() + "$child";// parenetName+"$child".
}
else if (definition.getFactoryBeanName() != null) {
generatedBeanName = definition.getFactoryBeanName() + "$created";//factroyBeanName+"$created".
}
}
if (!StringUtils.hasText(generatedBeanName)) {//如果这三个还是为空,那么久报错
throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " +
"'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
}
String id = generatedBeanName;
if (isInnerBean) {//如果当前的class是一个innerBean,这个时候,需要完成的是 generateBeanName +"#"+当前Bean对应的Hashcode的唯一值。
// Inner bean: generate identity hashcode suffix.
id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
}
else {
// Top-level bean: use plain class name.
// Increase counter until the id is unique.
int counter = -1;
while (counter == -1 || registry.containsBeanDefinition(id)) {//如果当前的beanRegistry中如果包括了对应BeanName了。这个时候需要不断的对当前counter进行自增。
counter++;
id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
}
}
return id;
}
4.6.1.5 构造BeanDefinitionHolder
将GenericBeanDefinition和beanName和aliasName一起构造一个BeanDefinitionHolder对象。
4.6.2 扩展当前BeanDefinitionHolder
BeanDefinitionHolder decorateBeanDefinitionIfRequired(
Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd)
这个当中完成的功能,主要是用户在Element中自定义了attribute和子childNode:
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
BeanDefinitionHolder finalDefinition = definitionHolder;//这个是解析完成的BeanDefinitionHolder。
// Decorate based on custom attributes first.这个主要是用户在Element中定义的 attribute的信息。
NamedNodeMap attributes = ele.getAttributes();//获取到所有的attribute。
for (int i = 0; i < attributes.getLength(); i++) {
Node node = attributes.item(i);
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);//如果其中有用户自定义的一些命名空间的内容,这个时候需要额外的调用对应NameSpaceHandlerResolver对象来对当前的对象进行额外的操作。
}
// Decorate based on custom nested elements.这个表示在当前Element中定义的 childNode信息。这些childNode是用户自定义相关的内容。
NodeList children = ele.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}
4.6.3 注册BeanDefinition到BeanDefintionRegistry
将构造好的一个Bean写到BeanDefinitionRegistry中去:
调用了一个util方法:BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
看一下这个方法是如何实现的:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();//获取到对应的beanName。
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); //这个方法是将当前生成的GenericBeanDefinition。
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);//将别名注册到BeanDefinitionRegistry中去。
}
}
}
看下在DefaultListableBeanFactory是如何注册的这个看下:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)//beanName 和 beanDefinition
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {//如果这个对象是AbstractBeanDefinition的实例。需要进行验证一下
try {
((AbstractBeanDefinition) beanDefinition).validate();//如果bean中有BeanClass对象,同时,Bean中有 OverrideMethod的时候,这个时候需要测试一下。
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);//获取到当前beanName在当前 Registry中已经存在的。
if (oldBeanDefinition != null) {//如果 这个是替换
if (!isAllowBeanDefinitionOverriding()) { //如果不允许替换,直接抛异常。
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {//判断一下不同的bean的role,这个时候需要打印一条提示日志。
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {//如果当前的bean和旧bean不相同的时候,这个时候就打印日志。
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);//将当前的bean添加到beanMap中去。 }
else {
if (hasBeanCreationStarted()) {//创建BeanMap是否开始了。这个时候判断一下当前的 alreadyCreated是否已经开始创建bean了
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {//对当前对象进行加锁
this.beanDefinitionMap.put(beanName, beanDefinition);//将beanDefinition添加到Map中去。
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);//修改过的beanDefinitions的数量。
updatedDefinitions.addAll(this.beanDefinitionNames);//将旧的beanDedinitions添加到updateDefinitions中去、
updatedDefinitions.add(beanName);//然后将当前的beanName添加到 updateBeanDefinitions。
this.beanDefinitionNames = updatedDefinitions;//这个时候使用 copyOfWrite来实现BeanDefinition的设置。
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);//如果有手动添加的单例Bean,这个时候需要将当前的bean删除掉。
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// 如果还没有开始创建,同时也不是覆盖
this.beanDefinitionMap.put(beanName, beanDefinition);//将当前的bean添加到bean中去
this.beanDefinitionNames.add(beanName);//beanDefinitionNames添加beanName
this.manualSingletonNames.remove(beanName);//从手动单例Name中删除 beanName的信息。
}
this.frozenBeanDefinitionNames = null;
}
//如果就的BeanDefinition不为空,或者是singletonBean的队列中包含了当前的bean。这个时候需要对当前的bean进行重新加载。
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
看下是如何复位BeanDefinition对象的:
protected void resetBeanDefinition(String beanName) {
// Remove the merged bean definition for the given bean, if already created.
clearMergedBeanDefinition(beanName);//首先将当前的beanName的bean对象从 mergedBeanDefinitionMap中移除
// Remove corresponding bean from singleton cache, if any. Shouldn't usually
// be necessary, rather just meant for overriding a context's default beans
// (e.g. the default StaticMessageSource in a StaticApplicationContext).
destroySingleton(beanName);//将当前的单例给删除掉
// Reset all bean definitions that have the given bean as parent (recursively).
//将所有的bean继承于当前的bean,都需要进行一下复位。
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
BeanDefinition bd = this.beanDefinitionMap.get(bdName);
if (beanName.equals(bd.getParentName())) {
resetBeanDefinition(bdName);
}
}
}
}