【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日,下午。