本文是针对Srping的
GitHub: https://github.com/lantaoGitHub/spring-framework.git
- 首先我们从
package org.springframework.lantao;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.
@Deprecated@SuppressWarnings({"serial", "all"})public class
- 我们直接看loadBeanDefinition方法,源码:
/** * Load bean definitions from the specified
上述源码可能看着比较长,但实际上这里并不是真正解析的地方,在这里做了如下:
1:从encodedResource已经封装的Resource获取InputStream;
2:如果encodedResource 中的 Encoding 不是 null 则同步设置 InputSource的 Encoding;
3:将解析动作委托给doLoadBeanDefinitions实现;
- 接下来我们继续看doLoadBeanDefinitions方法内容:
/** * Actually load bean definitions from the specified
当我们看着这个方法的时候,依旧不是真正的解析或注册的方法,在这里只是做了Document的加载,并将后续工作委托给了registerBeanDefinitions,registerBeanDefinitions方法的返回时注册Bean的个数;
- 我们继续看registerBeanDefinitions的源码:
/** * Register the bean definitions contained in the given DOM document. * Called by {@code loadBeanDefinitions}. * <p>Creates a new instance of the parser class and invokes * {@code registerBeanDefinitions} on it. * @param doc the DOM document * @param resource the resource descriptor (for context information) * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of parsing errors * @see #loadBeanDefinitions * @see #setDocumentReaderClass * @see BeanDefinitionDocumentReader#registerBeanDefinitions */public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { //实例化 BeanDefinitionDocumentReader BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); //获取之前的beanDefinition加载个数 int countBefore = getRegistry().getBeanDefinitionCount(); //加载
在registerBeanDefinitions方法具体实现:
1:通过BeanUtils.instantiateClass(this.documentReaderClass)的方法实例化BeanDefinitionDocumentReader;
2:通过DefaultListAbleBeanFactory中的beanDefinitionMap.size()获取之前注册bean的个数,(beanDefinitionMap是存储最终的
3:将解析
4:记录本次加载个数并返回;
- 继续看BeanDefinitionDocumentReader的registerBeanDefinitions方法:
/** * This implementation parses bean definitions according to the "spring-beans" XSD * (or DTD, historically). * <p>Opens a DOM Document; then initializes the default settings * specified at the {@code <beans/>} level; then parses the contained bean definitions. */@Overridepublic void registerBeanDefinitions(Document doc,
- registerBeanDefinitions并没有做什么,我们继续看doRegisterBeanDefinitions方法:
/** * Register each bean definition within the given root {@code <beans/>} element. */@SuppressWarnings("deprecation") // for Environment.acceptsProfiles(String...)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); //验证
在doRegisterBeanDefinitions方法中验证
- parseBeanDefinitions方法的源码:
/** * Parse the elements at the root level in the document: * "import", "alias", "bean". * @param root the DOM root element of the document */protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { //验证
parseBeanDefinitions方法中已经开始对标签进行解析,区分默认标签和自定义标签,我们本次只对默认标签的源码进行解析,自定义标签自行DeBug,
- parseDefaultElement方法的源码:
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标签 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); }}
到这里我们可以看到,spring对import/bean/alias/beans的解析过程,对于beans的解析无法就是解析beans中的bean标签,spring直接又重新调用了doRegisterBeanDefinitions方法,我们接下来进行对bean标签的解析;
- processBeanDefinition方法:
/** * Process the given bean element, parsing the bean definition * and registering it with the registry. */protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { //委托BeanDefinitionParserDelegate的parseBeanDefinitionElement方法进行元素解析并返回 //BeanDefinitionHolder实例,BeanDefinitionHolder已经包含了配置文件中的各种属性 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //当BeanDefinitionHolder返回不null的情况,若存在默认标签下的子标签再有自定义的属性,还需要再次解析 if (bdHolder != null) { //解析默认标签中的自定义标签 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. // 进行实例注册注册操作是BeanDefinitionReaderUtisl.registerBeanDefinition进行处理 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)); }}
在processBeanDefinition方法中,spring做了两件事情:
1:委托BeanDefinitionParserDelegate的parseBeanDefinitionElement方法进行元素解析并返回BeanDefinitionHolder实例,BeanDefinitionHolder已经包含了配置文件中的各种属性
2:通过上获得的BeanDefinitionHolder进行bean的注册操作,通BeanDefinitionReaderUtils.registerBeanDefinition方法;
- 通过delegate.parseBeanDefinitionElement方法进行
/** * Parses the supplied {@code <bean>} element. May return {@code null} * if there were errors during parse. Errors are reported to the * {@link org.springframework.beans.factory.parsing.ProblemReporter}. */@Nullablepublic BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { //解析id属性 String id = ele.getAttribute(ID_ATTRIBUTE); //解析name属性 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); //分割name属性 List<String> aliases = new ArrayList<>(); 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.isTraceEnabled()) { logger.trace("No
在parseBeanDefinitionElement方法中做了三件事:
1:解析id/name;
2:检查name的唯一性;
3:将信息封装到 beanDefinition中,接下来直接看parseBeanDefinitionElement方法;
- parseBeanDefinitionElement源码:
/** * Parse the bean definition itself, without regard to name or aliases. May return * {@code null} if problems occurred during the parsing of the bean definition. */@Nullablepublic AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, @Nullable BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; //解析classname属性 if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } String parent = null; //解析parent属性 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } try { //创建用于承载属性的AbstractBeanDefinition类型的 AbstractBeanDefinition bd = createBeanDefinition(className, parent); //解析bean的各种属性 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); //提取description bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); //解析meta (元数据) parseMetaElements(ele, bd); //解析Lookup-method 书中53页有使用方法 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); //解析replaced-method 书中55页有使用方法 parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); //构造函数 参数 //解析constructor-arg 书中replaced-method后边 parseConstructorArgElements(ele, bd); //解析Property 书中replaced-method后边 parsePropertyElements(ele, bd); //解析Qualifier 书中Property后边 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来承载各种parseBeanDefinitionAttributes方法解析了lookUp-method(方法注入),replaced-method(替换方法或方法返回值),构造函数参数constructor-arg,property属性,Qualifier属性等;上述方法的源码就不一一展示了,无非都是通过Element进行解析;
- 接下来看真正注册的代码 BeanDefinitionReaderUtils.registerBeanDefinition
@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { //beanName不可为空 Assert.hasText(beanName, "Bean name must not be empty"); //beanDefinition不可为空 Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { //校验 MethodOverrides,MethodOverrides在解析并组装beanDefinition时有提到 ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } //beanDefinitionMap 存储实例的全局Map 使用ConcurrentHashMap 线程安全 BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); //如果已经注册 处理内容 if (existingDefinition != null) { //是否覆盖 if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } else if (existingDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isInfoEnabled()) { 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 (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } this.beanDefinitionMap.put(beanName, beanDefinition); } else { //判断是否已经至少创建过一次 使用AbstractBeanFactory.alreadyCreated来判断 if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) 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; if (this.manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } } else { // 仍处于启动注册阶段 // 注册 beanDefinitionMap 新实例 beanName + beanDefinition this.beanDefinitionMap.put(beanName, beanDefinition); // 增加beanDefinitionNames this.beanDefinitionNames.add(beanName); // 清除缓存 this.manualSingletonNames.remove(beanName); } // 清除缓存 this.frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); }}
上述代码中首先验证了beanName和BeannDefinition不可为空,然后继续校验了MethodOverridesMethodOverrides在解析并组装beanDefinition时lookup-method和recpse-method的源码中有提到,继续判断beanDefinitionMap是否存在该bean,如果bean已经存在,通过allowBeanDefinitionOverriding属性判断是否可覆盖,反之则抛出异常;如果不存在则需要判断本次是否是第一次注册bean,如果是则初始化beanDefinitionMap后进行put操作,反之直接put beanDefinitionMap完成注册;
至此我们已经看完了整个
原文转载:http://www.shaoqun.com/a/631651.html
亚马逊t恤:https://www.ikjzd.com/w/1932
吴佳:https://www.ikjzd.com/w/1770
本文是针对Srping的GitHub:https://github.com/lantaoGitHub/spring-framework.git首先我们从packageorg.springframework.lantao;importorg.springframework.beans.factory.BeanFactory;importorg.springframework.beans.fac
邓白氏集团:https://www.ikjzd.com/w/582
亚马逊应用商店:https://www.ikjzd.com/w/531
跨境通网站:https://www.ikjzd.com/w/1329
新手课堂 |让你5分钟搞懂亚马逊Listing页面!:https://www.ikjzd.com/home/18367
亚马逊卖家支持:https://www.ikjzd.com/w/806
谷歌营销:如何利用目标客户匹配工具挖掘潜在用户:https://www.ikjzd.com/home/132116
没有评论:
发表评论