Spring ioc容器启动流程—obtainFreshBeanFactory

来源:互联网 发布:什么下载软件 编辑:程序博客网 时间:2024/06/05 09:45

        本文以XmlWebApplicationContext启动为例说明spring ioc容器启动流程。

        obtainFreshBeanFactory的主要工作是创建DefaultListableBeanFactory实例,解析xml配置文件,注册bean。

工作流程概览


         obtainFreshBeanFactory的主要工作在AbstractRefreshableApplicationContext类中refreshBeanFactory方法中完成,这里完成DefaultListableBeanFactory的创建及初始化,之后在XmlWebApplicationContext类中的loadBeanDefinitions(DefaultListableBeanFactory beanFactory)方法中将bean的load工作转交给XmlBeanDefinitionReader。

核心工作流程

创建DefaultListableBeanFactory

AbstractRefreshableApplicationContext.java

protected DefaultListableBeanFactory createBeanFactory() {return new DefaultListableBeanFactory(getInternalParentBeanFactory());}

解析xml配置文件,即loadBeanDefinitions

资源形式的转化过程


        xml配置文件中的<bean>元素最终会解析实例化为BeanDefinition,注册到DefaultListableBeanFactory。

configLocation到Resource

       利用resourceLoader属性读取相应的locationPattern为Resource:


InputSource到Document

        先对Resource的资源模式进行校验,是.xsd还是.dtd方式解析等,XmlBeanDefinitionReader的属性documentLoader(其为DefaultDocumentLoader类型)加载InputSource为Document,这里关键步骤是用ResourceEntityResolver定位到xsd资源来帮助解析xml文件:


Document到Element

       XmlBeanDefinitionReader创建DefaultBeanDefinitionDocumentReader实例,将解析工作交给它,DefaultBeanDefinitionDocumentReader初步解析Document,获取根Element,创建BeanDefinitionParserDelegate实例,将解析Element分为两大类:DefaultElement、CustomElement,其中DefaultElement包括<import>、<alias>、<bean>、嵌套的<beans>,其余的都为CustomElement:


        DefaultBeanDefinitionDocumentReader解析Element过程中,利用代理模式,将解析工作委托给BeanDefinitionParserDelegate进行:

DefaultBeanDefinitionDocumentReader.java

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {  if (delegate.isDefaultNamespace(root)) { // Element的namespaceURI为空或为"http://www.springframework.org/schema/beans"  NodeList nl = root.getChildNodes();  for (int i = 0; i < nl.getLength(); i++) { // 循环遍历所有Element元素的下一级  Node node = nl.item(i);  if (node instanceof Element) {  Element ele = (Element) node;  if (delegate.isDefaultNamespace(ele)) { // 是否为默认的namespaceUri  parseDefaultElement(ele, delegate); // 处理默认的namespaceUri Element  }  else {  delegate.parseCustomElement(ele); // 处理Custom Element  }  }  }  }  else {  delegate.parseCustomElement(root);  }  }

解析默认的Element

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { // 解析import ElementimportBeanDefinitionResource(ele);}else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { // 解析alias ElementprocessAliasRegistration(ele);}else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { // 解析bean ElementprocessBeanDefinition(ele, delegate);}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // 解析内嵌beans Element// recursedoRegisterBeanDefinitions(ele);}}

解析<import>:

protected void importBeanDefinitionResource(Element ele) {String location = ele.getAttribute(RESOURCE_ATTRIBUTE); // 获取import element的resource属性if (!StringUtils.hasText(location)) {getReaderContext().error("Resource location must not be empty", ele);return;}// Resolve system properties: e.g. "${user.dir}"location = environment.resolveRequiredPlaceholders(location);Set<Resource> actualResources = new LinkedHashSet<Resource>(4);// Discover whether the location is an absolute or relative URIboolean absoluteLocation = false;try {absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();}catch (URISyntaxException ex) {// cannot convert to an URI, considering the location relative// unless it is the well-known Spring prefix "classpath*:"}// Absolute or relative?if (absoluteLocation) { // location是否为绝对路径try {int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);if (logger.isDebugEnabled()) {logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");}}catch (BeanDefinitionStoreException ex) {getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, ex);}}else {// No URL -> considering resource location as relative to the current file.try {int importCount;Resource relativeResource = getReaderContext().getResource().createRelative(location);if (relativeResource.exists()) {importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);   // 加载import指定的xml配置文件actualResources.add(relativeResource);}else {String baseLocation = getReaderContext().getResource().getURL().toString();importCount = getReaderContext().getReader().loadBeanDefinitions(StringUtils.applyRelativePath(baseLocation, location), actualResources);}if (logger.isDebugEnabled()) {logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");}}catch (IOException ex) {getReaderContext().error("Failed to resolve current resource location", ele, ex);}catch (BeanDefinitionStoreException ex) {getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",ele, ex);}}Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));}

解析<bean>:

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); // 解析Element为BeanDefinitionif (bdHolder != null) {bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// 将BeanDefinition注册到DefaultListableBeanFactory的beanDefinitionMap中BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());}catch (BeanDefinitionStoreException ex) {getReaderContext().error("Failed to register bean definition with name '" +bdHolder.getBeanName() + "'", ele, ex);}// 发送Component注册的消息getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));}}BeanDefinitionParserDelegate.javapublic BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {return parseBeanDefinitionElement(ele, null);}public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {String id = ele.getAttribute(ID_ATTRIBUTE); // 获取bean的id属性String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);// 获取bean的name属性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);}// 这里解析Element为GenericBeanDefinitionAbstractBeanDefinition 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;}public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {this.parseState.push(new BeanEntry(beanName));String className = null;if (ele.hasAttribute(CLASS_ATTRIBUTE)) {className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); // 获取bean element的class属性}try {String parent = null;if (ele.hasAttribute(PARENT_ATTRIBUTE)) {parent = ele.getAttribute(PARENT_ATTRIBUTE);}// 利用反射实例化bean为GenericBeanDefinitionAbstractBeanDefinition bd = createBeanDefinition(className, parent);// 解析Element中对应配置文件的属性,set到GenericBeanDefinition中parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));parseMetaElements(ele, bd);parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); // 解析Override方法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;}// 利用反射实例化GenericBeanDefinitionprotected AbstractBeanDefinition createBeanDefinition(String className, String parentName)throws ClassNotFoundException {return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());}// 解析Element对应的配置文件属性,设置到GenericBeanDefinitionpublic AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,BeanDefinition containingBean, AbstractBeanDefinition bd) {if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {// Spring 2.x "scope" attributebd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {error("Specify either 'scope' or 'singleton', not both", ele);}}else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {// Spring 1.x "singleton" attributebd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ?BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);}else if (containingBean != null) {// Take default from containing bean in case of an inner bean definition.bd.setScope(containingBean.getScope());}if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));}String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);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));}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));}if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));}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);}}if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);if (!"".equals(destroyMethodName)) {bd.setDestroyMethodName(destroyMethodName);}}else {if (this.defaults.getDestroyMethod() != null) {bd.setDestroyMethodName(this.defaults.getDestroyMethod());bd.setEnforceDestroyMethod(false);}}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;}
解析<alias>:

DefaultBeanDefinitionDocumentReader.javaprotected void processAliasRegistration(Element ele) {String name = ele.getAttribute(NAME_ATTRIBUTE); // 获取alias element的name属性String alias = ele.getAttribute(ALIAS_ATTRIBUTE);// 获取alias element的alias属性boolean valid = true;if (!StringUtils.hasText(name)) {getReaderContext().error("Name must not be empty", ele);valid = false;}if (!StringUtils.hasText(alias)) {getReaderContext().error("Alias must not be empty", ele);valid = false;}if (valid) {try {// 将alias注册到DefaultListableBeanFactory的aliasMap属性中getReaderContext().getRegistry().registerAlias(name, alias); }catch (Exception ex) {getReaderContext().error("Failed to register alias '" + alias +"' for bean with name '" + name + "'", ele, ex);}// 发送alias注册的消息getReaderContext().fireAliasRegistered(name, alias, extractSource(ele)); }}SimpleAliasRegistry.javapublic void registerAlias(String name, String alias) {Assert.hasText(name, "'name' must not be empty");Assert.hasText(alias, "'alias' must not be empty");if (alias.equals(name)) {this.aliasMap.remove(alias);}else {if (!allowAliasOverriding()) {String registeredName = this.aliasMap.get(alias);if (registeredName != null && !registeredName.equals(name)) {throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +name + "': It is already registered for name '" + registeredName + "'.");}}checkForAliasCircle(name, alias);this.aliasMap.put(alias, name); // 将alias注册到aliasMap中}}

解析CustomElement

BeanDefinitionParserDelegate.javapublic BeanDefinition parseCustomElement(Element ele) {return parseCustomElement(ele, null);}public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {String namespaceUri = getNamespaceURI(ele); // 获取element的namespaceUri属性// 利用XmlReaderContext的DefaultNamespaceHandlerResolver namespaceHandlerResolver属性,根据namespaceUri获取对应的NamespaceHandlerNamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);if (handler == null) {error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);return null;}return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));}

       这里以解析<context:component-scan>为例,说明BeanDefinitionParserDelegate是如何parseCustomElement的。

<!-- 扫描注解文件  --><context:component-scan base-package="com.java" />
       首先,确定NamespaceHandler:parseCustomElement根据Element的namespaceURI,确定NamespaceHandler为ContextNamespaceHandler,这样BeanDefinitionParserDelegate将解析的工作委托给具体Namespace的NamespaceHandler:
public class ContextNamespaceHandler extends NamespaceHandlerSupport {public void init() {registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());}}


        其次,确定BeanDefinitionParser:在<context>的Namespace下,根据具体的标签"component-scan",确定BeanDefinitionParser为ComponentScanBeanDefinitionParser,这样NamespaceHandler将解析的工作委托给具体BeanDefinitionParser。ContextNamespaceHandler针对其命名下的"component-scan"、"annotation-config"标签等对应不同的BeanDefinitionParser,从而完成Element到BeanDefinition的解析工作:



NamespaceHandlerSupport.java:// NamespaceHandler将解析工作委托给BeanDefinitionParserpublic BeanDefinition parse(Element element, ParserContext parserContext) {// 将解析工作委托给ComponentScanBeanDefinitionParserreturn findParserForElement(element, parserContext).parse(element, parserContext); }private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {// 获取Element对应的localName,该例为"component-scan"String localName = parserContext.getDelegate().getLocalName(element); // ContextNamespaceHandler在init方法中注册了很多BeanDefinitionParser到HashMap<String, BeanDefinitionParser> parsers,这里从中获取对应的BeanDefinitionParser parser = this.parsers.get(localName);if (parser == null) {parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionParser for element [" + localName + "]", element);}return parser;}ComponentScanBeanDefinitionParser.java// 解析Element为BeanDefinition,且完成注册工作public BeanDefinition parse(Element element, ParserContext parserContext) {// 获取"base-package"属性String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE),ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);// Actually scan for bean definitions and register them.ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); // 用ClassPathBeanDefinitionScanner扫描"base-package"下的BeanDefinitionSet<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); // 注册CompositeComponentDefinitionregisterComponents(parserContext.getReaderContext(), beanDefinitions, element); return null;}// 创建ClassPathBeanDefinitionScanner对象且进行配置protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {XmlReaderContext readerContext = parserContext.getReaderContext();boolean useDefaultFilters = true;if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));}// Delegate bean definition registration to scanner class.ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters);scanner.setResourceLoader(readerContext.getResourceLoader());scanner.setEnvironment(parserContext.getDelegate().getEnvironment());scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));}try {parseBeanNameGenerator(element, scanner);}catch (Exception ex) {readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause());}try {parseScope(element, scanner);}catch (Exception ex) {readerContext.error(ex.getMessage(), readerContext.extractSource(element), ex.getCause());}parseTypeFilters(element, scanner, readerContext, parserContext);return scanner;}protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters);}ClassPathBeanDefinitionScanner.javaprotected Set<BeanDefinitionHolder> doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();for (String basePackage : basePackages) {// 查找@Component的ClassSet<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) {ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);candidate.setScope(scopeMetadata.getScopeName());String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}if (candidate instanceof AnnotatedBeanDefinition) {AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}if (checkCandidate(beanName, candidate)) { // 检测Annotation bean是否已经有同名的bean在BeanFactory注册,如果没有则为trueBeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);beanDefinitions.add(definitionHolder);// 注册bean到DefaultListableBeanFactory中registerBeanDefinition(definitionHolder, this.registry); }}}return beanDefinitions;}ClassPathScanningCandidateComponentProvider.javapublic Set<BeanDefinition> findCandidateComponents(String basePackage) {Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();try {String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + "/" + this.resourcePattern;// 获取"classpath*:com/java/**/*.class"所有的ResourceResource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);boolean traceEnabled = logger.isTraceEnabled();boolean debugEnabled = logger.isDebugEnabled();for (Resource resource : resources) {if (traceEnabled) {logger.trace("Scanning " + resource);}if (resource.isReadable()) {try {MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);if (isCandidateComponent(metadataReader)) { // 判断是否是ComponentScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);sbd.setResource(resource);sbd.setSource(resource);if (isCandidateComponent(sbd)) { // 判断sbd isConcrete且isIndependentif (debugEnabled) {logger.debug("Identified candidate component class: " + resource);}candidates.add(sbd);}else {if (debugEnabled) {logger.debug("Ignored because not a concrete top-level class: " + resource);}}}else {if (traceEnabled) {logger.trace("Ignored because not matching any filter: " + resource);}}}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, ex);}}else {if (traceEnabled) {logger.trace("Ignored because not readable: " + resource);}}}}catch (IOException ex) {throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);}return candidates;}

0 0
原创粉丝点击