zoukankan      html  css  js  c++  java
  • Spring Boot 配置类2-解析逻辑(processConfigBeanDefinitions方法中的循环体)

    一、执行入口

    解析方法在processConfigBeanDefinitions方法里的do while循环体中

    		do {
    			parser.parse(candidates);
    			parser.validate();
    
    			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
    			configClasses.removeAll(alreadyParsed);
    
    			// Read the model and create bean definitions based on its content
    			if (this.reader == null) {
    				this.reader = new ConfigurationClassBeanDefinitionReader(
    						registry, this.sourceExtractor, this.resourceLoader, this.environment,
    						this.importBeanNameGenerator, parser.getImportRegistry());
    			}
    			this.reader.loadBeanDefinitions(configClasses);
    			alreadyParsed.addAll(configClasses);
    
    			candidates.clear();
    			if (registry.getBeanDefinitionCount() > candidateNames.length) {
    				String[] newCandidateNames = registry.getBeanDefinitionNames();
    				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
    				Set<String> alreadyParsedClasses = new HashSet<>();
    				for (ConfigurationClass configurationClass : alreadyParsed) {
    					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
    				}
    				for (String candidateName : newCandidateNames) {
    					if (!oldCandidateNames.contains(candidateName)) {
    						BeanDefinition bd = registry.getBeanDefinition(candidateName);
    						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
    								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
    							candidates.add(new BeanDefinitionHolder(bd, candidateName));
    						}
    					}
    				}
    				candidateNames = newCandidateNames;
    			}
    		}
    		while (!candidates.isEmpty());
    

      

    二、循环体逻辑

    我们已解析beanName是sb2Application为例

    1、首先进入parser.parse(candidates)

    1) 最重要的方法就是parse

    ;

    2) 然后进入parse(AnnotationMetadata metadata, String beanName)方法

    3) 进入processConfigurationClass(ConfigurationClass configClass)方法

     4) 我们重点关注doProcessConfigurationClass这个方法

    	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
    			throws IOException {
    
    		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    			// Recursively process any member (nested) classes first
    			processMemberClasses(configClass, sourceClass);
    		}
    
    		// Process any @PropertySource annotations
    		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
    				sourceClass.getMetadata(), PropertySources.class,
    				org.springframework.context.annotation.PropertySource.class)) {
    			if (this.environment instanceof ConfigurableEnvironment) {
    				processPropertySource(propertySource);
    			}
    			else {
    				logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
    						"]. Reason: Environment must implement ConfigurableEnvironment");
    			}
    		}
    
    		// Process any @ComponentScan annotations
    		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
    				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    		if (!componentScans.isEmpty() &&
    				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
    			for (AnnotationAttributes componentScan : componentScans) {
    				// The config class is annotated with @ComponentScan -> perform the scan immediately
    				Set<BeanDefinitionHolder> scannedBeanDefinitions =
    						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
    				// Check the set of scanned definitions for any further config classes and parse recursively if needed
    				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
    					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
    					if (bdCand == null) {
    						bdCand = holder.getBeanDefinition();
    					}
    					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
    						parse(bdCand.getBeanClassName(), holder.getBeanName());
    					}
    				}
    			}
    		}
    
    		// Process any @Import annotations
    		processImports(configClass, sourceClass, getImports(sourceClass), true);
    
    		// Process any @ImportResource annotations
    		AnnotationAttributes importResource =
    				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    		if (importResource != null) {
    			String[] resources = importResource.getStringArray("locations");
    			Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
    			for (String resource : resources) {
    				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
    				configClass.addImportedResource(resolvedResource, readerClass);
    			}
    		}
    
    		// Process individual @Bean methods
    		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    		for (MethodMetadata methodMetadata : beanMethods) {
    			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    		}
    
    		// Process default methods on interfaces
    		processInterfaces(configClass, sourceClass);
    
    		// Process superclass, if any
    		if (sourceClass.getMetadata().hasSuperClass()) {
    			String superclass = sourceClass.getMetadata().getSuperClassName();
    			if (superclass != null && !superclass.startsWith("java") &&
    					!this.knownSuperclasses.containsKey(superclass)) {
    				this.knownSuperclasses.put(superclass, configClass);
    				// Superclass found, return its annotation metadata and recurse
    				return sourceClass.getSuperClass();
    			}
    		}
    
    		// No superclass -> processing is complete
    		return null;
    	}
    

      

    a)该方法首先判断是否有Component注解。如果有,则调用processMemberClasses方法。

    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    			// Recursively process any member (nested) classes first
    			processMemberClasses(configClass, sourceClass);
    		}
    

      

    processMemberClasses方法里回调用doProcessConfigurationClass的父方法processConfigurationClass,形成递归调用。

    b)接着处理PropertySource 注解配置

    Process any @PropertySource annotations
    

      

    c)接着处理ComponentScan注解

    Process any @ComponentScan annotations
    

      


    d)、接着处理Import注解。可以通过Import导入相应的类
    Process any @Import annotations
    

      

    e)、接着处理ImportResource注解。
    Process any @ImportResource annotations
    

      

    f)、接着处理Bean方法。
    Process individual @Bean methods
    

      

    g)、接着处理默认方法
    Process default methods on interfaces
    

      

    
    
    h)、接着处理父类。
    Process superclass, if any
    

      

    2、解析完成后调用parser.validate();验证方法。验证解析的合法性

    parser.validate();
    

      

    3、读取BeanMethod注册BeanDeanDefinition

    	if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    		}
    

      

    4、处理新引入的BeanDefinition

     然后继续执行循环体

  • 相关阅读:
    struts2文件上传大小限制问题
    kindeditor使用方法
    ajaxFileUpload SyntaxError: syntax error
    Attempted to lock an already-locked dir异常解决方法
    Simditor图片上传
    心理学
    Vue.JS
    SQL Server 日常维护经典应用
    12 个 JS 技巧
    Linq to js
  • 原文地址:https://www.cnblogs.com/linlf03/p/12434440.html
Copyright © 2011-2022 走看看