源代码分析,是一件既痛苦又快乐的事情,看别人写的代码是通过的,但当你能够看明白的时候,相信快乐也会随之而来,为了减少痛苦,更快的带来快乐,
本文以spring框架的XmlBeanFactory为入手点进行分析
首先来打开该类的代码,我们将看到如下代码:
1 public class XmlBeanFactory extends DefaultListableBeanFactory { 2 3 private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); 4 5 public XmlBeanFactory(Resource resource) throws BeansException { 6 this(resource, null); 7 } 8 9 public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { 10 super(parentBeanFactory); 11 this.reader.loadBeanDefinitions(resource); 12 } 13 14 }
这个类的代码很简单,一个成员对象加两个构造函数,从这里我们可以看出,最重要的地方在于最后一个构造函数:
1 public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { 2 super(parentBeanFactory); 3 this.reader.loadBeanDefinitions(resource); 4 }
第一句就是将父亲工厂交给父类的构造函数,
实际上最后也就是把父工厂保存到类的parentBeanFactory成员对象中,这个对象是在AbstractBeanFactory抽象类中定义的,而这个父工厂也会一直传递到该抽象类进行保存。
第二句就是整个类中最重要的地方了,顾名思义,它的目的是通过XmlBeanDefinitionReader这个XML的Reader从资源resource中(也就是你的配置文件)读取bean的定义。
接下来我们打开XmlBeanDefinitionReader的loadBeanDefinitions方法,我们可看到在这个方法里代码就一行,调用了一个同名不同参的方法,而参数是EncodedResource的一个实例,这个类实际上是Resource的一个包装类,用来保存资源的Encode的,
1 public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { 2 return loadBeanDefinitions(new EncodedResource(resource)); 3 }
那接下来我们再看被调用的loadBeanDefinitions方法,
1 public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { 2 Assert.notNull(encodedResource, "EncodedResource must not be null"); 3 if (logger.isInfoEnabled()) { 4 logger.info("Loading XML bean definitions from " + encodedResource.getResource()); 5 } 6 7 Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); 8 if (currentResources == null) { 9 currentResources = new HashSet<EncodedResource>(4); 10 this.resourcesCurrentlyBeingLoaded.set(currentResources); 11 } 12 if (!currentResources.add(encodedResource)) { 13 throw new BeanDefinitionStoreException( 14 "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); 15 } 16 try { 17 InputStream inputStream = encodedResource.getResource().getInputStream(); 18 try { 19 InputSource inputSource = new InputSource(inputStream); 20 if (encodedResource.getEncoding() != null) { 21 inputSource.setEncoding(encodedResource.getEncoding()); 22 } 23 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); 24 } 25 finally { 26 inputStream.close(); 27 } 28 } 29 catch (IOException ex) { 30 throw new BeanDefinitionStoreException( 31 "IOException parsing XML document from " + encodedResource.getResource(), ex); 32 } 33 finally { 34 currentResources.remove(encodedResource); 35 if (currentResources.isEmpty()) { 36 this.resourcesCurrentlyBeingLoaded.remove(); 37 } 38 } 39 }
这个方法里最主要的部分就是:
1 try { 2 InputStream inputStream = encodedResource.getResource().getInputStream(); 3 try { 4 InputSource inputSource = new InputSource(inputStream); 5 if (encodedResource.getEncoding() != null) { 6 inputSource.setEncoding(encodedResource.getEncoding()); 7 } 8 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); 9 } 10 finally { 11 inputStream.close(); 12 } 13 }
这里的目的是将资源包装成一个InputSource,连同Resource作为参数传递到doLoadBeanDefinitions方法
1 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) 2 throws BeanDefinitionStoreException { 3 try { 4 Document doc = doLoadDocument(inputSource, resource); 5 return registerBeanDefinitions(doc, resource); 6 } 7 catch (BeanDefinitionStoreException ex) { 8 throw ex; 9 } 10 catch (SAXParseException ex) { 11 throw new XmlBeanDefinitionStoreException(resource.getDescription(), 12 "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); 13 } 14 catch (SAXException ex) { 15 throw new XmlBeanDefinitionStoreException(resource.getDescription(), 16 "XML document from " + resource + " is invalid", ex); 17 } 18 catch (ParserConfigurationException ex) { 19 throw new BeanDefinitionStoreException(resource.getDescription(), 20 "Parser configuration exception parsing XML from " + resource, ex); 21 } 22 catch (IOException ex) { 23 throw new BeanDefinitionStoreException(resource.getDescription(), 24 "IOException parsing XML document from " + resource, ex); 25 } 26 catch (Throwable ex) { 27 throw new BeanDefinitionStoreException(resource.getDescription(), 28 "Unexpected exception parsing XML document from " + resource, ex); 29 } 30 }
很遗憾,这个类没有什么实际作为,只有一些对异常的处理.把解析的逻辑委托给了doLoadDocument这个方法
然后调用registerBeanDefinitions方法,注册Bean的信息
1 protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception { 2 return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler, 3 getValidationModeForResource(resource), isNamespaceAware()); 4 }
就是为了将资源解释成为Document对象,这里不做详细解释,不了解的话请去看看关于JAXP的介绍。
1 public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, 2 ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception { 3 4 DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware); 5 if (logger.isDebugEnabled()) { 6 logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]"); 7 } 8 DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler); 9 return builder.parse(inputSource); 10 }
来看看registerBeanDefinitions的实现
1 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { 2 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); 3 documentReader.setEnvironment(this.getEnvironment()); 4 int countBefore = getRegistry().getBeanDefinitionCount(); 5 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); 6 return getRegistry().getBeanDefinitionCount() - countBefore; 7 }
在这里, 有一个BeanDefinitionDocumentReader接口, 实际上Spring对它有一个默认的实现类叫DefaultBeanDefinitionDocumentReader, 来看看它的家族
BeanDefinitionDocumentReader只有2个方法 ,
registerBeanDefinitions就是其中一个
1 public interface BeanDefinitionDocumentReader { 2 3 /** 4 * Set the Environment to use when reading bean definitions. 5 * <p>Used for evaluating profile information to determine whether a 6 * {@code <beans/>} document/element should be included or ignored. 7 */ 8 void setEnvironment(Environment environment); 9 10 /** 11 * Read bean definitions from the given DOM document and 12 * register them with the registry in the given reader context. 13 * @param doc the DOM document 14 * @param readerContext the current context of the reader 15 * (includes the target registry and the resource being parsed) 16 * @throws BeanDefinitionStoreException in case of parsing errors 17 */ 18 void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) 19 throws BeanDefinitionStoreException; 20 21 }
该方法需要两个参数, 一个是Document模型,这个应该是我们读取配置文件获取到的, 另一个是XmlReaderContext对象, 我们在上面方法中看到是通过createReaderContext(resource)得到的, 那就看看具体如何得到
1 public XmlReaderContext createReaderContext(Resource resource) { 2 return new XmlReaderContext(resource, this.problemReporter, this.eventListener, 3 this.sourceExtractor, this, getNamespaceHandlerResolver()); 4 }
能过构造函数new出来的, 且有一个重要参数resource
再继续来看DefaultBeanDefinitionDocumentReader对BeanDefinitionDocumentReader的registerBeanDefinitions方法实现
1 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { 2 this.readerContext = readerContext; 3 logger.debug("Loading bean definitions"); 4 Element root = doc.getDocumentElement(); 5 doRegisterBeanDefinitions(root); 6 }
是的
1 protected void doRegisterBeanDefinitions(Element root) { 2 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); 3 if (StringUtils.hasText(profileSpec)) { 4 Assert.state(this.environment != null, "Environment must be set for evaluating profiles"); 5 String[] specifiedProfiles = StringUtils.tokenizeToStringArray( 6 profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); 7 if (!this.environment.acceptsProfiles(specifiedProfiles)) { 8 return; 9 } 10 } 11 12 // Any nested <beans> elements will cause recursion in this method. In 13 // order to propagate and preserve <beans> default-* attributes correctly, 14 // keep track of the current (parent) delegate, which may be null. Create 15 // the new (child) delegate with a reference to the parent for fallback purposes, 16 // then ultimately reset this.delegate back to its original (parent) reference. 17 // this behavior emulates a stack of delegates without actually necessitating one. 18 BeanDefinitionParserDelegate parent = this.delegate; 19 this.delegate = createDelegate(this.readerContext, root, parent); 20 21 preProcessXml(root); 22 parseBeanDefinitions(root, this.delegate); 23 postProcessXml(root); 24 25 this.delegate = parent; 26 }
嘿嘿, 开始解析Dom了哦, 其中主要是parseBeanDefinitions方法, 来看看具体是如何解析的
这里创建了一个XmlBeanDefinitionParser接口的实现,这个接口的具体类是DefaultXmlBeanDefinitionParser,这个接口很简单,只有registerBeanDefinitions一个方法,这个方法的作用也很明了,就是用来注册Bean的定义的,所以说类和方法的名字一定要起得有意义,这样可以让人一看就大概了解其作用,减少了很多阅读代码的痛苦。废话不多说,我们打开DefaultXmlBeanDefinitionParser的registerBeanDefinitions方法,这个类就是解释XML配置文件的核心类了,打开registerBeanDefinitions方法后我们看到如下代码:
1 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { 2 if (delegate.isDefaultNamespace(root)) { 3 NodeList nl = root.getChildNodes(); 4 for (int i = 0; i < nl.getLength(); i++) { 5 Node node = nl.item(i); 6 if (node instanceof Element) { 7 Element ele = (Element) node; 8 if (delegate.isDefaultNamespace(ele)) { 9 parseDefaultElement(ele, delegate); 10 } 11 else { 12 delegate.parseCustomElement(ele); 13 } 14 } 15 } 16 } 17 else { 18 delegate.parseCustomElement(root); 19 } 20 }
看到了吧, 循环解析Domcument节点
parseDefaultElement方法和delegate的parseCustomElement方法
先来看parseDefaultElement方法
1 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { 2 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { 3 importBeanDefinitionResource(ele); 4 } 5 else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { 6 processAliasRegistration(ele); 7 } 8 else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { 9 processBeanDefinition(ele, delegate); 10 } 11 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { 12 // recurse 13 doRegisterBeanDefinitions(ele); 14 } 15 }
看到这就很清楚了, 就是根据节点的名称作不同解析, 如我们Spring配置文件中常有以下几种配置
<import resource="classpath:xxx" /> <bean id="car" class="entity.CarFactoryBean"> <property name="carInfo" value="超级跑车,400,2000000" /> </bean>
对<import>节点, 调用importBeanDefinitionResource方法解析, 此方法中, 又回到第一步读取配置文件并解析. 如此递归循环.
... if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } ...
对<alias>节点, 调用processAliasRegistration进行别名解析
... else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } ...
我们主要看对<bean>节点调用processBeanDefinition进行解析
... else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } ...
processBeanDefinition:
1 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { 2 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); 3 if (bdHolder != null) { 4 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); 5 try { 6 // Register the final decorated instance. 7 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); 8 } 9 catch (BeanDefinitionStoreException ex) { 10 getReaderContext().error("Failed to register bean definition with name '" + 11 bdHolder.getBeanName() + "'", ele, ex); 12 } 13 // Send registration event. 14 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); 15 } 16 }
嘿嘿, 又用到delegate对象了, 且调用它的parseBeanDefinitionElement方法, 返回一个BeanDefinitionHolder, 进去看它的parseBeanDefinitionElement方法
1 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { 2 return parseBeanDefinitionElement(ele, null); 3 }
parseBeanDefinitionElement
1 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { 2 String id = ele.getAttribute(ID_ATTRIBUTE); 3 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); 4 //解析id, name等属性, 5 List<String> aliases = new ArrayList<String>(); 6 if (StringUtils.hasLength(nameAttr)) { 7 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); 8 aliases.addAll(Arrays.asList(nameArr)); 9 } 10 11 String beanName = id; 12 if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { 13 beanName = aliases.remove(0); 14 if (logger.isDebugEnabled()) { 15 logger.debug("No XML 'id' specified - using '" + beanName + 16 "' as bean name and " + aliases + " as aliases"); 17 } 18 } 19 //并验证beanName是否唯一, 并将beanName保存在aliases中 20 if (containingBean == null) { 21 checkNameUniqueness(beanName, aliases, ele); 22 } 23 //解析bean定义本身,而不考虑名称或别名。可能返回null,如果bean定义的解析过程中出现的问题 24 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); 25 if (beanDefinition != null) { 26 if (!StringUtils.hasText(beanName)) { 27 try { 28 if (containingBean != null) { 29 beanName = BeanDefinitionReaderUtils.generateBeanName( 30 beanDefinition, this.readerContext.getRegistry(), true); 31 } 32 else { 33 beanName = this.readerContext.generateBeanName(beanDefinition); 34 // Register an alias for the plain bean class name, if still possible, 35 // if the generator returned the class name plus a suffix. 36 // This is expected for Spring 1.2/2.0 backwards compatibility. 37 String beanClassName = beanDefinition.getBeanClassName(); 38 if (beanClassName != null && 39 beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && 40 !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { 41 aliases.add(beanClassName); 42 } 43 } 44 if (logger.isDebugEnabled()) { 45 logger.debug("Neither XML 'id' nor 'name' specified - " + 46 "using generated bean name [" + beanName + "]"); 47 } 48 } 49 catch (Exception ex) { 50 error(ex.getMessage(), ele); 51 return null; 52 } 53 } 54 String[] aliasesArray = StringUtils.toStringArray(aliases); 55 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); 56 } 57 58 return null; 59 }
可以看到, 在BeanDefinitionHolder中保存了BeanDefinition的定义
OK, 重头戏开始, 最经典的部分出现了, 请看parseBeanDefinitionElement方法
1 public AbstractBeanDefinition parseBeanDefinitionElement( 2 Element ele, String beanName, BeanDefinition containingBean) { 3 4 this.parseState.push(new BeanEntry(beanName)); 5 6 String className = null; 7 if (ele.hasAttribute(CLASS_ATTRIBUTE)) { 8 className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); 9 } 10 11 try { 12 String parent = null; 13 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { 14 parent = ele.getAttribute(PARENT_ATTRIBUTE); 15 } 16 AbstractBeanDefinition bd = createBeanDefinition(className, parent); 17 18 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); 19 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); 20 21 parseMetaElements(ele, bd); 22 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); 23 parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); 24 25 parseConstructorArgElements(ele, bd); 26 parsePropertyElements(ele, bd); 27 parseQualifierElements(ele, bd); 28 29 bd.setResource(this.readerContext.getResource()); 30 bd.setSource(extractSource(ele)); 31 32 return bd; 33 } 34 catch (ClassNotFoundException ex) { 35 error("Bean class [" + className + "] not found", ele, ex); 36 } 37 catch (NoClassDefFoundError err) { 38 error("Class that bean class [" + className + "] depends on not found", ele, err); 39 } 40 catch (Throwable ex) { 41 error("Unexpected failure during bean definition parsing", ele, ex); 42 } 43 finally { 44 this.parseState.pop(); 45 } 46 47 return null; 48 }
在这个方法中, 解析了bean的所有属性, 有最常用的class, scope, lazy-init等等. 并返回一个AbstractBeanDefinition实例. 至于具体怎么解析, 就只能进一步跟踪了, 不过既然到了这一步, 已经明白了它的基本原理, 具体实现就不作介绍
1 public static AbstractBeanDefinition createBeanDefinition( 2 String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException { 3 4 GenericBeanDefinition bd = new GenericBeanDefinition(); 5 bd.setParentName(parentName); 6 if (className != null) { 7 if (classLoader != null) { 8 bd.setBeanClass(ClassUtils.forName(className, classLoader)); 9 } 10 else { 11 bd.setBeanClassName(className); 12 } 13 } 14 return bd; 15 }
这一步将节点解析成BeanDefinitionHolder对象, 再看看如何注册, 回到DefaultBeanDefinitionDocumentReader的processBeanDefinition方法
看到对解析到的bdHolder对象又做了decorateBeanDefinitionIfRequired操作, 来看看实现
1 public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) { 2 return decorateBeanDefinitionIfRequired(ele, definitionHolder, null); 3 }
decorateBeanDefinitionIfRequired
1 public BeanDefinitionHolder decorateBeanDefinitionIfRequired( 2 Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) { 3 4 BeanDefinitionHolder finalDefinition = definitionHolder; 5 6 // Decorate based on custom attributes first. 7 NamedNodeMap attributes = ele.getAttributes(); 8 for (int i = 0; i < attributes.getLength(); i++) { 9 Node node = attributes.item(i); 10 finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); 11 } 12 13 // Decorate based on custom nested elements. 14 NodeList children = ele.getChildNodes(); 15 for (int i = 0; i < children.getLength(); i++) { 16 Node node = children.item(i); 17 if (node.getNodeType() == Node.ELEMENT_NODE) { 18 finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); 19 } 20 } 21 return finalDefinition; 22 }
这里关键就2行代码,主要是做一些合法性验证,比如 文件头,语法,属性的合法性,由于代码过长不一一解释,代码如下
1 public BeanDefinitionHolder decorateIfRequired( 2 Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) { 3 4 String namespaceUri = getNamespaceURI(node); 5 if (!isDefaultNamespace(namespaceUri)) { 6 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); 7 if (handler != null) { 8 return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd)); 9 } 10 else if (namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) { 11 error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node); 12 } 13 else { 14 // A custom namespace, not to be handled by Spring - maybe "xml:...". 15 if (logger.isDebugEnabled()) { 16 logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]"); 17 } 18 } 19 } 20 return originalDef; 21 }
回到DefaultBeanDefinitionDocumentReade.processBeanDefinition这个方法 只行完delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);之后
接着调用了BeanDefinitionReaderUtils的registerBeanDefinition方法注册bdHolder, 来看看如何实现的
1 public static void registerBeanDefinition( 2 BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) 3 throws BeanDefinitionStoreException { 4 5 // Register bean definition under primary name. 6 String beanName = definitionHolder.getBeanName(); 7 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); 8 9 // Register aliases for bean name, if any. 10 String[] aliases = definitionHolder.getAliases(); 11 if (aliases != null) { 12 for (String aliase : aliases) { 13 registry.registerAlias(beanName, aliase); 14 } 15 } 16 }
1 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) 2 throws BeanDefinitionStoreException { 3 4 Assert.hasText(beanName, "Bean name must not be empty"); 5 Assert.notNull(beanDefinition, "BeanDefinition must not be null"); 6 7 if (beanDefinition instanceof AbstractBeanDefinition) { 8 try { 9 ((AbstractBeanDefinition) beanDefinition).validate(); 10 } 11 catch (BeanDefinitionValidationException ex) { 12 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, 13 "Validation of bean definition failed", ex); 14 } 15 } 16 17 synchronized (this.beanDefinitionMap) { 18 BeanDefinition oldBeanDefinition = this.beanDefinitionMap.get(beanName); 19 if (oldBeanDefinition != null) { 20 if (!this.allowBeanDefinitionOverriding) { 21 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, 22 "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + 23 "': There is already [" + oldBeanDefinition + "] bound."); 24 } 25 else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { 26 // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE 27 if (this.logger.isWarnEnabled()) { 28 this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + 29 " with a framework-generated bean definition ': replacing [" + 30 oldBeanDefinition + "] with [" + beanDefinition + "]"); 31 } 32 } 33 else { 34 if (this.logger.isInfoEnabled()) { 35 this.logger.info("Overriding bean definition for bean '" + beanName + 36 "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); 37 } 38 } 39 } 40 else { 41 this.beanDefinitionNames.add(beanName); 42 this.frozenBeanDefinitionNames = null; 43 } 44 this.beanDefinitionMap.put(beanName, beanDefinition); 45 } 46 47 resetBeanDefinition(beanName); 48 }
这里, 看到了一个最最重要的对象就是beanDefinitionMap, 这个map存放了所有的bean对象, 和我们通常讲的容器概念最为接近, getBean时实际是也是从这里领取对象, 相同的还有一个beanDefinitionNames, 但这个只保存bean的名称
完成上面之后, 还有一步操作beanFactory.registerAlias(beanName, aliases[i]);
这个实现实际是上AbstractBeanFactory抽象类所定义的
是不是特兴奋, 已经揭开它神秘的面纱了
定义 -> 定位 -> 装载 -> 注册 这几步已经完成了, 以后继续看Spring是如何创建bean及实例化的
多数内容来自:http://leayer.iteye.com/blog/806016