zoukankan      html  css  js  c++  java
  • 【spring源码分析】IOC容器初始化(三)

    前言:在【spring源码分析】IOC容器初始化(二)中已经得到了XML配置文件的Document实例,下面分析bean的注册过程。


    XmlBeanDefinitionReader#registerBeanDefinitions(Document doc, Resource resource)

     1 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
     2         // #1.创建BeanDefinitionDocumentReader对象
     3         BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
     4         // #2.获取已注册过的BeanDefinition对象个数
     5         int countBefore = getRegistry().getBeanDefinitionCount();
     6         // #3.创建XmlReaderContext对象[主要为了关联命名空间处理器],并注册BeanDefinition
     7         documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
     8         // 返回新注册的BeanDefinition对象个数
     9         return getRegistry().getBeanDefinitionCount() - countBefore;
    10     }

     分析:

    • 首先创建BeanDefinitionDocumentReader对象。
    • 获取已注册过的BeanDefinition个数。
    • 然后进入核心处理流程,注册BeanDefinition。
    • 最后返回新注册的BeanDefinition个数。

    XmlBeanDefinitionReader#createBeanDefinitionDocumentReader

    1 protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
    2         return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
    3     }

    分析:通过反射得到BeanDefinitionDocumentReader对象。

    DefaultListableBeanFactory#getBeanDefinitionCount

    1     /**
    2      * 存储beanName->BeanDefinition的集合map<br/>
    3      * Map of bean definition objects, keyed by bean name.
    4      */
    5     private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    6 
    7     public int getBeanDefinitionCount() {
    8         return this.beanDefinitionMap.size();
    9     }

    分析:逻辑简单,就是从beanDefinitionMap中获取当前的size,注意beanDefinitionMap存储的就是注册的BeanDefinition集合。

    DefaultBeanDefinitionDocumentReader#registerBeanDefinitions(Document doc, XmlReaderContext readerContext)

    1     public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    2         this.readerContext = readerContext;
    3         logger.debug("Loading bean definitions");
    4         // 获取XML Document对象的root元素
    5         Element root = doc.getDocumentElement();
    6         // 执行注册
    7         doRegisterBeanDefinitions(root);
    8     }

    分析:

    • 首先获取XML Document对象的root元素。
    • 执行注册。

    这里需要注意一点:registerBeanDefinitions的第二个入参,调用入口如下:

    注意这里调用了XmlBeanDefinitionReader#createReaderContext:

    1     /**
    2      * 创建一个文档资源读取器<br/>
    3      * Create the {@link XmlReaderContext} to pass over to the document reader.
    4      */
    5     public XmlReaderContext createReaderContext(Resource resource) {
    6         return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
    7                 this.sourceExtractor, this, getNamespaceHandlerResolver());
    8     }

    分析:

    这里主要关注XmlBeanDefinitionReader#getNamespaceHandlerResolver()函数:

     1 /**
     2      * 主要就是获得默认空间处理器,为后续解析标签做准备<br/>
     3      * Lazily create a default NamespaceHandlerResolver, if not set before.
     4      *
     5      * @see #createDefaultNamespaceHandlerResolver()
     6      */
     7     public NamespaceHandlerResolver getNamespaceHandlerResolver() {
     8         if (this.namespaceHandlerResolver == null) {
     9             this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
    10         }
    11         return this.namespaceHandlerResolver;
    12     }
    13 
    14     /**
    15      * Create the default implementation of {@link NamespaceHandlerResolver} used if none is specified.
    16      * Default implementation returns an instance of {@link DefaultNamespaceHandlerResolver}.
    17      */
    18     protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
    19         ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
    20         return new DefaultNamespaceHandlerResolver(cl);
    21     }

    分析:

    该函数主要是获得默认空间处理器,为后续解析标签做准备。最终切入DefaultNamespaceHandlerResolver中。DefaultNamespaceHandlerResolver中有两个函数值得我们关注:

     1 public NamespaceHandler resolve(String namespaceUri) {
     2         // 获取所有已经配置的Handler映射
     3         Map<String, Object> handlerMappings = getHandlerMappings();
     4         // 根据namespaceUri获取handler信息:这里一般都是类路径
     5         Object handlerOrClassName = handlerMappings.get(namespaceUri);
     6         // 不存在
     7         if (handlerOrClassName == null) {
     8             return null;
     9         // 已经初始化
    10         } else if (handlerOrClassName instanceof NamespaceHandler) {
    11             return (NamespaceHandler) handlerOrClassName;
    12         // 需要进行初始化
    13         } else {
    14             String className = (String) handlerOrClassName;
    15             try {
    16                 // 通过反射获得类,并创建NamespaceHandler对象
    17                 Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
    18                 if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
    19                     throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
    20                             "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
    21                 }
    22                 NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
    23                 // 初始化NameSpaceHandler
    24                 namespaceHandler.init();
    25                 // 添加到缓存
    26                 handlerMappings.put(namespaceUri, namespaceHandler);
    27                 return namespaceHandler;
    28             } catch (ClassNotFoundException ex) {
    29                 throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
    30                         "] for namespace [" + namespaceUri + "]", ex);
    31             } catch (LinkageError err) {
    32                 throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
    33                         className + "] for namespace [" + namespaceUri + "]", err);
    34             }
    35         }
    36     }
    37 
    38 private Map<String, Object> getHandlerMappings() {
    39         Map<String, Object> handlerMappings = this.handlerMappings;
    40         // 这里使用了double-check的方式,进行延迟加载
    41         if (handlerMappings == null) {
    42             synchronized (this) {
    43                 handlerMappings = this.handlerMappings;
    44                 if (handlerMappings == null) {
    45                     if (logger.isTraceEnabled()) {
    46                         logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]");
    47                     }
    48                     try {
    49                         // 读取handlerMappingsLocation
    50                         Properties mappings =
    51                                 PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
    52                         if (logger.isTraceEnabled()) {
    53                             logger.trace("Loaded NamespaceHandler mappings: " + mappings);
    54                         }
    55                         // 初始化到handlerMappings中
    56                         handlerMappings = new ConcurrentHashMap<>(mappings.size());
    57                         CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
    58                         this.handlerMappings = handlerMappings;
    59                     } catch (IOException ex) {
    60                         throw new IllegalStateException(
    61                                 "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
    62                     }
    63                 }
    64             }
    65         }
    66         return handlerMappings;
    67     }

    分析:

    • resolve主要是通过命名空间uri得到命名空间处理器,如果没有初始化,则会进行初始化,并缓存。
    • getHandlerMappings函数使用了Double-Check进行延迟加载,获取所有命名空间处理器。

    DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

     1 protected void doRegisterBeanDefinitions(Element root) {
     2         // Any nested <beans> elements will cause recursion in this method. In
     3         // order to propagate and preserve <beans> default-* attributes correctly,
     4         // keep track of the current (parent) delegate, which may be null. Create
     5         // the new (child) delegate with a reference to the parent for fallback purposes,
     6         // then ultimately reset this.delegate back to its original (parent) reference.
     7         // this behavior emulates a stack of delegates without actually necessitating one.
     8 
     9         // 记录老的BeanDefinitionParserDelegate对象
    10         BeanDefinitionParserDelegate parent = this.delegate;
    11 
    12         // 创建BeanDefinitionParserDelegate对象,并对delegate进行默认设置
    13         this.delegate = createDelegate(getReaderContext(), root, parent);
    14 
    15         // 检测<beans/>标签的命名空间是否为空,或者是否为"http://www.springframework.org/schema/beans"
    16         if (this.delegate.isDefaultNamespace(root)) {
    17             // 处理profile属性
    18             String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
    19             if (StringUtils.hasText(profileSpec)) {
    20                 // 如果profile属性有值,则使用分隔符进行切分,因为可能有多个profile
    21                 String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
    22                         profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
    23                 // 检测profile是否有效,如果无效,则不进行注册
    24                 if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
    25                     if (logger.isInfoEnabled()) {
    26                         logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
    27                                 "] not matching: " + getReaderContext().getResource());
    28                     }
    29                     return;
    30                 }
    31             }
    32         }
    33         // 解析xml前置处理,该方法为空,主要留给用户自定义处理,增强扩展性
    34         preProcessXml(root);
    35         // 核心函数,进行xml解析
    36         parseBeanDefinitions(root, this.delegate);
    37         // 解析xml后置处理,该方法也为空,主要留给用户自定义处理,增强扩展性
    38         postProcessXml(root);
    39         // 将delegate回到老的BeanDefinitionParserDelegate对象
    40         this.delegate = parent;
    41     }

    分析:

    • 首先记录旧的BeanDefinitionParserDelegate,然后创建一个新的BeanDefinitionParserDelegate对象,因为对BeanDefinition的解析会进行委托。
    • 检测<beans/>标签的正确性,处理profile属性。
    • preProcessXml:解析xml的前置处理,默认为空,主要留给用户自定义实现,增强扩展性;postProcessXml:解析xml的后置处理,默认也为空,同样留给用户自定义实现。
    • parseBeanDefinitions:解析xml的核心函数,将在下面进行详细分析。

    DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

     1 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
     2         // 如果根节点使用默认命名空间,则执行默认解析
     3         if (delegate.isDefaultNamespace(root)) {
     4             NodeList nl = root.getChildNodes();
     5             // 遍历子节点
     6             for (int i = 0; i < nl.getLength(); i++) {
     7                 Node node = nl.item(i);
     8                 if (node instanceof Element) {
     9                     Element ele = (Element) node;
    10                     // 如果该节点使用默认命名空间,则执行默认解析
    11                     if (delegate.isDefaultNamespace(ele)) {
    12                         parseDefaultElement(ele, delegate);
    13                         // 如果该节点使用非默认命名空间,则执行自定义解析
    14                     } else {
    15                         delegate.parseCustomElement(ele);
    16                     }
    17                 }
    18             }
    19             // 否则使用自定义解析根节点
    20         } else {
    21             delegate.parseCustomElement(root);
    22         }
    23     }

    分析:

    首先判断根节点是否使用默认命名空间:

    • 如果是默认命名空间,则遍历其子节点进行解析。
    • 如果不是默认命名空间,则直接使用parseCustomElement进行解析。

    DefaultBeanDefinitionDocumentReader#parseDefaultElement

     1 /**
     2      * 解析默认标签
     3      *
     4      * @param ele      当前元素节点
     5      * @param delegate BeanDefinition解析委托
     6      */
     7     private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
     8         // import标签
     9         if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
    10             // 主要流程获取import标签的source属性,然后通过loadBeanDefinitions加载BeanDefinition
    11             importBeanDefinitionResource(ele);
    12         } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // alias标签
    13             processAliasRegistration(ele);
    14         } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // bean标签,主要解析标签
    15             processBeanDefinition(ele, delegate);
    16         } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // beans标签
    17             // recurse
    18             doRegisterBeanDefinitions(ele);
    19         }
    20     }

    分析:

    默认标签的解析分为4个分支:①import;②alias;③bean;④beans标签(进行递归,再进行解析)。这里我们主要分析日常中最常用的bean标签,其他标签解析的大致流程差不多,后面进行补充。

    DefaultBeanDefinitionDocumentReader#processBeanDefinition

     1 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
     2         // 进行bean标签解析
     3         // 如果解析成功,则返回BeanDefinitionHolder,BeanDefinitionHolder为name和alias的BeanDefinition对象
     4         // 如果解析失败,则返回null
     5         BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
     6         if (bdHolder != null) {
     7             // 进行标签处理,主要对bean标签的相关属性进行处理 如: p:name="测试用例"
     8             bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
     9             try {
    10                 // 注册BeanDefinition
    11                 // Register the final decorated instance.
    12                 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    13             } catch (BeanDefinitionStoreException ex) {
    14                 getReaderContext().error("Failed to register bean definition with name '" +
    15                         bdHolder.getBeanName() + "'", ele, ex);
    16             }
    17             // 发出响应时间,通知监听器,已完成该bean标签的解析
    18             // Send registration event.
    19             getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    20         }
    21     }

    分析:

    • 首先使用委托对bean标签进行基础解析(核心处理流程)。
    • 解析成功后,再处理bean标签的一些其他属性。
    • 最后注册BeanDefintion。

    BeanDefinitionParserDelegate#parseBeanDefinitionElement

     1 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
     2         return parseBeanDefinitionElement(ele, null);
     3     }
     4 
     5 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
     6         // 解析id和name属性
     7         String id = ele.getAttribute(ID_ATTRIBUTE);
     8         String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
     9 
    10         // 计算别名集合
    11         List<String> aliases = new ArrayList<>();
    12         if (StringUtils.hasLength(nameAttr)) {
    13             String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
    14             aliases.addAll(Arrays.asList(nameArr));
    15         }
    16 
    17         // beanName,优先使用id
    18         String beanName = id;
    19         // 若beanName为空,则使用alias的第一个
    20         if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
    21             // 将alias第一个元素移除别名集合
    22             beanName = aliases.remove(0);
    23             if (logger.isTraceEnabled()) {
    24                 logger.trace("No XML 'id' specified - using '" + beanName +
    25                         "' as bean name and " + aliases + " as aliases");
    26             }
    27         }
    28 
    29         // 检查beanName的唯一性
    30         if (containingBean == null) {
    31             checkNameUniqueness(beanName, aliases, ele);
    32         }
    33 
    34         // 解析bean标签的属性,构造AbstractBeanDefinition
    35         AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    36         if (beanDefinition != null) {
    37             // 如果beanName为空
    38             if (!StringUtils.hasText(beanName)) {
    39                 try {
    40                     // 如果containingBean不为null
    41                     if (containingBean != null) {
    42                         // 生成唯一的beanName
    43                         beanName = BeanDefinitionReaderUtils.generateBeanName(
    44                                 beanDefinition, this.readerContext.getRegistry(), true);
    45                     } else {
    46                         // 生成唯一的beanName
    47                         beanName = this.readerContext.generateBeanName(beanDefinition);
    48                         // Register an alias for the plain bean class name, if still possible,
    49                         // if the generator returned the class name plus a suffix.
    50                         // This is expected for Spring 1.2/2.0 backwards compatibility.
    51                         // 判断beanName是否被使用
    52                         String beanClassName = beanDefinition.getBeanClassName();
    53                         if (beanClassName != null &&
    54                                 beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
    55                                 !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
    56                             aliases.add(beanClassName);
    57                         }
    58                     }
    59                     if (logger.isTraceEnabled()) {
    60                         logger.trace("Neither XML 'id' nor 'name' specified - " +
    61                                 "using generated bean name [" + beanName + "]");
    62                     }
    63                 } catch (Exception ex) {
    64                     error(ex.getMessage(), ele);
    65                     return null;
    66                 }
    67             }
    68             // 创建BeanDefinitionHolder对象
    69             String[] aliasesArray = StringUtils.toStringArray(aliases);
    70             return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    71         }
    72 
    73         return null;
    74     }

    分析: 

    • 获取bean标签的id与name属性,spring在解析bean的时候,优先使用的id值。
    • 检查beanName的唯一性,如果不唯一,则会报错。
    • (核心)解析bean的属性,构造AbstractBeanDefinition对象。
    • 如果beanDefiniton对象的beanName为空,还要为其生成一个beanName,为注册BeanDefinition做准备。
    • 最后返回BeanDefinitionHolder对象。

    BeanDefinitionParserDelegate#parseBeanDefinitionElement

     1 public AbstractBeanDefinition parseBeanDefinitionElement(
     2             Element ele, String beanName, @Nullable BeanDefinition containingBean) {
     3 
     4         // 为解析bean元素加一个状态
     5         this.parseState.push(new BeanEntry(beanName));
     6 
     7         // 解析class属性
     8         String className = null;
     9         if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
    10             className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    11         }
    12         // 解析parent属性
    13         String parent = null;
    14         if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
    15             parent = ele.getAttribute(PARENT_ATTRIBUTE);
    16         }
    17 
    18         try {
    19             // 创建承载属性的AbstractBeanDefinition对象
    20             AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    21             // 解析bean的各种默认属性
    22             parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    23             // 提取description
    24             bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
    25 
    26             // 这里会解析bean标签内部的很多子元素,放入bd中
    27 
    28             // #1.解析元数据 <meta/>
    29             parseMetaElements(ele, bd);
    30             // #2.解析lookup-method属性 <lookup-method/>
    31             // lookup-method:获取器注入,把一个方法声明为返回某种类型的bean,但方法的实际返回的bean是在配置文件里配置的
    32             parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
    33 
    34             // #3.解析replace-method属性 <replace-method/>
    35             // replace-method:可在运行时调用新的方法替换现有的方法,还能动态的更新原有方法的逻辑
    36             parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    37 
    38             // #4.解析构造函数参数 <constructor-arg/>
    39             parseConstructorArgElements(ele, bd);
    40             // #5.解析property子元素 <property/>
    41             parsePropertyElements(ele, bd);
    42             // #6.解析qualifier子元素 <qualifier/>
    43             parseQualifierElements(ele, bd);
    44 
    45             // 设置resource
    46             bd.setResource(this.readerContext.getResource());
    47             bd.setSource(extractSource(ele));
    48 
    49             return bd;
    50         } catch (ClassNotFoundException ex) {
    51             error("Bean class [" + className + "] not found", ele, ex);
    52         } catch (NoClassDefFoundError err) {
    53             error("Class that bean class [" + className + "] depends on not found", ele, err);
    54         } catch (Throwable ex) {
    55             error("Unexpected failure during bean definition parsing", ele, ex);
    56         } finally {
    57             this.parseState.pop();
    58         }
    59 
    60         return null;
    61     }

    分析:

    • 首先获取bean标签的class和parent属性,用于创建承载属性的AbstractBeanDefinition对象[由这两个属性就可以创建AbstractBeanDefinition对象了]。
    • 接下来就是对bean标签进行各种解析,并将解析的数据赋值到AbstractBeanDefinition中。

    BeanDefinitionParserDelegate#createBeanDefinition

     1 protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
     2             throws ClassNotFoundException {
     3 
     4         return BeanDefinitionReaderUtils.createBeanDefinition(
     5                 parentName, className, this.readerContext.getBeanClassLoader());
     6     }
     7 
     8 
     9 //BeanDefinitionReaderUtils#creatBeanDefinition
    10 
    11 public static AbstractBeanDefinition createBeanDefinition(
    12             @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
    13 
    14         // 创建GenericBeanDefinition对象
    15         GenericBeanDefinition bd = new GenericBeanDefinition();
    16         // 设置parentName
    17         bd.setParentName(parentName);
    18         // 在className不为空的情况下,进行相关属性的设置
    19         if (className != null) {
    20             // 如果classLoader不为空,这里就会直接通过反射加载类 ?为了提升速度
    21             if (classLoader != null) {
    22                 bd.setBeanClass(ClassUtils.forName(className, classLoader));
    23             }
    24             // 设置beanClassName的名字
    25             else {
    26                 bd.setBeanClassName(className);
    27             }
    28         }
    29         return bd;
    30     }

    分析:

    BeanDefinition的创建是通过BeanDefinitionReaderUtils#createBeanDefinition方法实现的,代码逻辑简单,主要注意生成的BeanDefinition对象是GenericBeanDefinition

    BeanDefinitionParserDelegate#parseBeanDefinitionAttributes

     1 public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
     2                                                                 @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
     3         // 如果有singleton属性则抛出异常,因为singleton属性已进行升级
     4         if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
     5             error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
     6             // 解析scope属性
     7         } else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
     8             bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
     9             // 如果BeanDefinition不为空,则使用当前BeanDefinition的scope
    10         } else if (containingBean != null) {
    11             // Take default from containing bean in case of an inner bean definition.
    12             bd.setScope(containingBean.getScope());
    13         }
    14         // 解析abstract属性
    15         if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
    16             bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
    17         }
    18 
    19         // 解析lazy-init属性 lazy-init属性默认为false
    20         String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
    21         if (isDefaultValue(lazyInit)) {
    22             lazyInit = this.defaults.getLazyInit();
    23         }
    24         bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
    25 
    26         // 解析autowire属性
    27         String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
    28         bd.setAutowireMode(getAutowireMode(autowire));
    29 
    30         // 解析depends-on属性
    31         if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
    32             String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
    33             bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
    34         }
    35 
    36         // 解析autowire-candidate属性
    37         String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
    38         if (isDefaultValue(autowireCandidate)) {
    39             String candidatePattern = this.defaults.getAutowireCandidates();
    40             if (candidatePattern != null) {
    41                 String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
    42                 bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
    43             }
    44         } else {
    45             bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
    46         }
    47 
    48         // 解析primary属性
    49         if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
    50             bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
    51         }
    52 
    53         // 解析init-method属性 设置bean的初始值方法
    54         if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
    55             String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
    56             bd.setInitMethodName(initMethodName);
    57         } else if (this.defaults.getInitMethod() != null) {
    58             bd.setInitMethodName(this.defaults.getInitMethod());
    59             bd.setEnforceInitMethod(false);
    60         }
    61 
    62         // 解析destroy-method属性
    63         if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
    64             String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
    65             bd.setDestroyMethodName(destroyMethodName);
    66         } else if (this.defaults.getDestroyMethod() != null) {
    67             bd.setDestroyMethodName(this.defaults.getDestroyMethod());
    68             bd.setEnforceDestroyMethod(false);
    69         }
    70 
    71         // 解析factory-method属性
    72         if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
    73             bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
    74         }
    75         // 解析factory-bean属性
    76         if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
    77             bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
    78         }
    79 
    80         return bd;
    81     }

    分析:

    该函数是对bean标签的默认属性做解析,最终解析后的值封装在BeanDefinition中,代码逻辑简单,函数中已给出相应注释。这里要注意一点lazy-init属性的默认值为false。

    介于篇幅原因,这里不在分析bean标签默认属性的解析过程,后续会对一些重要的方法进行补充,下面将分析BeanDefinition的注册过程。

    总结

    本文主要分析了BeanDefinition注册之前的一些准备工作,还未进入核心流程,后面将进入BeanDefinition注册的核心流程。

    ps:笔者希望每篇文章不要写太长,尽量做到短小精悍。


    by Shawn Chen,2018.12.8日,下午。

  • 相关阅读:
    2019 苏宁控股java面试笔试题 (含面试题解析)
    2019 58同城java面试笔试题 (含面试题解析)
    2019 搜狐java面试笔试题 (含面试题解析)
    2019 拼多多java面试笔试题 (含面试题解析)
    2019 新浪 java面试笔试题 (含面试题解析)
    doubango(2)--底层协议栈结构分析
    doubango(1)--从协议栈结构说起
    doubango简介
    WebRTC VoiceEngine使用简单Demo
    WebRTC音视频引擎研究(2)--VoiceEngine音频编解码器数据结构以及参数设置
  • 原文地址:https://www.cnblogs.com/developer_chan/p/10072189.html
Copyright © 2011-2022 走看看