spring的自动配置原理

springboot配置文件的装配过程

1、springboot在启动的时候会加载主配置类,开启了@EnableAutoConfiguration。

2、@EnableAutoConfiguration的作用:

  • 利用AutoConfigurationImportSelector类给容器导入一些组件。

  • 调用AutoConfigurationImportSelector中的selectImports方法的内容,返回一个AutoConfigurationEntry

    1、AutoConfigurationEntry autoConfigurationEntry=getAutoConfigurationEntry(autoConfigurationMetadata,
          annotationMetadata);
    ------
    2、List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    ------
    3、protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
    				getBeanClassLoader());
    		Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
    				+ "are using a custom packaging, make sure that file is correct.");
    		return configurations;
    	}

  • 可以看到调用的是SpringFactoriesLoader.loadFactoryNames,最终调用了loadSpringFactories方法,获取META-INF/spring.factories资源文件,key为

    org.springframework.boot.autoconfigure.EnableAutoConfiguration
  • public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    		String factoryTypeName = factoryType.getName();
    		return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    	}
    
    	private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    		MultiValueMap<String, String> result = cache.get(classLoader);
    		if (result != null) {
    			return result;
    		}
    
    		try {
    			Enumeration<URL> urls = (classLoader != null ?
    					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
    					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
    			result = new LinkedMultiValueMap<>();
    			while (urls.hasMoreElements()) {
    				URL url = urls.nextElement();
    				UrlResource resource = new UrlResource(url);
    				Properties properties = PropertiesLoaderUtils.loadProperties(resource);
    				for (Map.Entry<?, ?> entry : properties.entrySet()) {
    					String factoryTypeName = ((String) entry.getKey()).trim();
    					for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
    						result.add(factoryTypeName, factoryImplementationName.trim());
    					}
    				}
    			}
    			cache.put(classLoader, result);
    			return result;
    		}
    		catch (IOException ex) {
    			throw new IllegalArgumentException("Unable to load factories from location [" +
    					FACTORIES_RESOURCE_LOCATION + "]", ex);
    		}
    	}

    总结:将类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;每一个xxxAutoConfiguration类都是容器中的一个组件,最后都加入到容器中,用来做自动配置,每一个自动配置类都可以进行自动配置功能

  • 3、以上为自动装配的原理,具体详细源码执行过程如下

    • 1、在springboot的启动过程中,执行到org.springframework.boot.SpringApplication#run
    • public ConfigurableApplicationContext run(String... args) {
      		StopWatch stopWatch = new StopWatch();
      		stopWatch.start();
      		ConfigurableApplicationContext context = null;
      		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
      		configureHeadlessProperty();
      		SpringApplicationRunListeners listeners = getRunListeners(args);
      		listeners.starting();
      		try {
      			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
      			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
      			configureIgnoreBeanInfo(environment);
      			Banner printedBanner = printBanner(environment);
      			context = createApplicationContext();
      			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
      					new Class[] { ConfigurableApplicationContext.class }, context);
                  //此处为自动装配的重要步骤,主要将启动类注入到beanfactory
      			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
      			refreshContext(context);
      			afterRefresh(context, applicationArguments);
      			stopWatch.stop();
      			if (this.logStartupInfo) {
      				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
      			}
      			listeners.started(context);
      			callRunners(context, applicationArguments);
      		}
      		catch (Throwable ex) {
      			handleRunFailure(context, ex, exceptionReporters, listeners);
      			throw new IllegalStateException(ex);
      		}
      
      		try {
      			listeners.running(context);
      		}
      		catch (Throwable ex) {
      			handleRunFailure(context, ex, exceptionReporters, null);
      			throw new IllegalStateException(ex);
      		}
      		return context;
      	}
      2、在prepareContext方法中最终调用load方法
    • 1、private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
      			SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
      		context.setEnvironment(environment);
      		postProcessApplicationContext(context);
      		applyInitializers(context);
      		listeners.contextPrepared(context);
      		if (this.logStartupInfo) {
      			logStartupInfo(context.getParent() == null);
      			logStartupProfileInfo(context);
      		}
      		// Add boot specific singleton beans
      		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
      		beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
      		if (printedBanner != null) {
      			beanFactory.registerSingleton("springBootBanner", printedBanner);
      		}
      		if (beanFactory instanceof DefaultListableBeanFactory) {
      			((DefaultListableBeanFactory) beanFactory)
      					.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
      		}
      		if (this.lazyInitialization) {
      			context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
      		}
      		// Load the sources
      		Set<Object> sources = getAllSources();
      		Assert.notEmpty(sources, "Sources must not be empty");
              //load方法完成该功能
      		load(context, sources.toArray(new Object[0]));
      		listeners.contextLoaded(context);
      	}
      
      2、	/**
      	 * Load beans into the application context.
      	 * @param context the context to load beans into
      	 * @param sources the sources to load
      	 * 加载bean对象到context中
      	 */
      	protected void load(ApplicationContext context, Object[] sources) {
      		if (logger.isDebugEnabled()) {
      			logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
      		}
              //获取bean对象定义的加载器
      		BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
      		if (this.beanNameGenerator != null) {
      			loader.setBeanNameGenerator(this.beanNameGenerator);
      		}
      		if (this.resourceLoader != null) {
      			loader.setResourceLoader(this.resourceLoader);
      		}
      		if (this.environment != null) {
      			loader.setEnvironment(this.environment);
      		}
      		loader.load();
      	}
      
      	/**
      3、	 * Load the sources into the reader.
      	 * @return the number of loaded beans
      	 */
      	int load() {
      		int count = 0;
      		for (Object source : this.sources) {
      			count += load(source);
      		}
      		return count;
      	}
      
      
      
      3、load方法最终执行的是BeanDefinitionLoader中的load方法
      //实际记载bean的方法
      private int load(Object source) {
      		Assert.notNull(source, "Source must not be null");
              //如果是class类型,启用注解类型,这里启动类为class类型,执行该方法
      		if (source instanceof Class<?>) {
      			return load((Class<?>) source);
      		}
              //如果是resource类型,启动xml解析
      		if (source instanceof Resource) {
      			return load((Resource) source);
      		}
              //如果是package类型,启用扫描包,例如@ComponentScan
      		if (source instanceof Package) {
      			return load((Package) source);
      		}
              //如果是字符串类型,直接加载
      		if (source instanceof CharSequence) {
      			return load((CharSequence) source);
      		}
      		throw new IllegalArgumentException("Invalid source type " + source.getClass());
      	}
      
      
      4、判断是否资源的类型,决定使用groovy加载还是使用注解的方式进行加载
    • private int load(Class<?> source) {
              //判断使用groovy脚本
      		if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
      			// Any GroovyLoaders added in beans{} DSL can contribute beans here
      			GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
      			load(loader);
      		}
              //使用注解加载,由于启动类的@SpringBootApplication属于@Component,所以进入到此方法
      		if (isComponent(source)) {
      			this.annotatedReader.register(source);
      			return 1;
      		}
      		return 0;
      	}
      5、isComponent方法是判断当前类否包含@Component注解,但我们发现启动类中并没有该注解,继续更进发现MergedAnnotations类传入了一个参数SearchStrategy.TYPE_HIERARCHY(查找继承关系中是否包含这个注解),经过层层进入:@SpringBootApplication-->@SpringBootConfiguration-->@Configuration-->@Component,当找到@Component注解之后,会把该对象注册到AnnotatedBeanDefinitionReader对象中
      private boolean isComponent(Class<?> type) {
         // This has to be a bit of a guess. The only way to be sure that this type is
         // eligible is to make a bean definition out of it and try to instantiate it.
         if (MergedAnnotations.from(type, SearchStrategy.TYPE_HIERARCHY).isPresent(Component.class)) {
            return true;
         }
         // Nested anonymous classes are not eligible for registration, nor are groovy
         // closures
         return !type.getName().matches(".*\\$_.*closure.*") && !type.isAnonymousClass()
               && type.getConstructors() != null && type.getConstructors().length != 0;
      }
      
      	/**
      	 * Register a bean from the given bean class, deriving its metadata from
      	 * class-declared annotations.
      	 * 从给定的bean class中注册一个bean对象,从注解中找到相关的元数据,这里主要是把启动类注册到到beanfactory中
      	 */
      	private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
      			@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
      			@Nullable BeanDefinitionCustomizer[] customizers) {
      
      		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
      		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
      			return;
      		}
      
      		abd.setInstanceSupplier(supplier);
      		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
      		abd.setScope(scopeMetadata.getScopeName());
      		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
      
      		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
      		if (qualifiers != null) {
      			for (Class<? extends Annotation> qualifier : qualifiers) {
      				if (Primary.class == qualifier) {
      					abd.setPrimary(true);
      				}
      				else if (Lazy.class == qualifier) {
      					abd.setLazyInit(true);
      				}
      				else {
      					abd.addQualifier(new AutowireCandidateQualifier(qualifier));
      				}
      			}
      		}
      		if (customizers != null) {
      			for (BeanDefinitionCustomizer customizer : customizers) {
      				customizer.customize(abd);
      			}
      		}
      
      		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
      		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
      		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
      	}
      
      	/**
      	 * Register the given bean definition with the given bean factory.
      	 * 注册启动类,如果有别名可以设置别名
      	 */
      	public static void registerBeanDefinition(
      			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      			throws BeanDefinitionStoreException {
      
      		// Register bean definition under primary name.
      		String beanName = definitionHolder.getBeanName();
      		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
      
      		// Register aliases for bean name, if any.
      		String[] aliases = definitionHolder.getAliases();
      		if (aliases != null) {
      			for (String alias : aliases) {
      				registry.registerAlias(beanName, alias);
      			}
      		}
      	}
      
      6、自动装配真正入口,是从refresh开始
@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
                // 此处是自动装配的入口
				invokeBeanFactoryPostProcessors(beanFactory);
            }
7、执行invokeBeanFactoryPostProcessors完成bean的实例化
/**
	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
	 * respecting explicit order if given.
	 * <p>Must be called before singleton instantiation.
	 */
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        //开始执行beanFactoryPostProcessor对应实现类,需要知道的是beanFactoryPostProcessor是spring的扩展接口,在刷新容器之前,该接口可以用来修改bean元数据信息
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}
8、invokeBeanFactoryPostProcessors具体执行过程
public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
			//开始遍历三个内部类,如果属于BeanDefinitionRegistryPostProcessor子类,加入到bean注册的集合,否则加入到regularPostProcessors
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the bean factory post-processors apply to them!
			// Separate between BeanDefinitionRegistryPostProcessors that implement
			// PriorityOrdered, Ordered, and the rest.
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            //通过BeanDefinitionRegistryPostProcessor获取到对应的处理类“org.springframework.context.annotation.internalConfigurationAnnotationProcessor”,但是需要注意的是这个类在springboot中搜索不到,这个类的完全限定名在AnnotationConfigEmbeddedWebApplicationContext中,在进行初始化的时候会装配几个类,在创建AnnotatedBeanDefinitionReader对象的时候会将该类注册到bean对象中,此处可以看到internalConfigurationAnnotationProcessor为bean名称,容器中真正的类是ConfigurationClassPostProcessor
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            //首先执行类型为PriorityOrdered的BeanDefinitionRegistryPostProcessor
            //PriorityOrdered类型表明为优先执行
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    //获取对应的bean
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    //用来存储已经执行过的BeanDefinitionRegistryPostProcessor
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
            //开始执行装配逻辑 主要是执行后置处理器ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            //其次执行类型为Ordered的BeanDefinitionRegistryPostProcessor
            //Ordered表明按顺序执行
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            //循环中执行类型不为PriorityOrdered,Ordered类型的BeanDefinitionRegistryPostProcessor
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.	
            //执行父类方法,优先执行注册处理类
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            //执行有规则处理类
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// Clear cached merged bean definitions since the post-processors might have
		// modified the original metadata, e.g. replacing placeholders in values...
		beanFactory.clearMetadataCache();
	}

9、 层层跟进 ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法,最终发现会执行到在ConfigurationClassParser类中,此类是所有配置类的解析类,所有的解析逻辑在parser.parse(candidates)中

public void parse(Set<BeanDefinitionHolder> configCandidates) {
		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();
			try {
                //是否是注解类
				if (bd instanceof AnnotatedBeanDefinition) {
					parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
				}
				else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
					parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
				}
				else {
					parse(bd.getBeanClassName(), holder.getBeanName());
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
			}
		}
    	//执行配置类
		this.deferredImportSelectorHandler.process();
	}
-------------------
    	protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(metadata, beanName));
	}
-------------------
    protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
			return;
		}

		ConfigurationClass existingClass = this.configurationClasses.get(configClass);
		if (existingClass != null) {
			if (configClass.isImported()) {
				if (existingClass.isImported()) {
					existingClass.mergeImportedBy(configClass);
				}
				// Otherwise ignore new imported config class; existing non-imported class overrides it.
				return;
			}
			else {
				// Explicit bean definition found, probably replacing an import.
				// Let's remove the old one and go with the new one.
				this.configurationClasses.remove(configClass);
				this.knownSuperclasses.values().removeIf(configClass::equals);
			}
		}

		// Recursively process the configuration class and its superclass hierarchy.
		SourceClass sourceClass = asSourceClass(configClass);
		do {
            //循环处理bean,如果有父类,则处理父类,直至结束
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);

		this.configurationClasses.put(configClass, configClass);
	}

10、进入到doProcessConfigurationClass方法,此方法是支持注解配置的核心逻辑

/**
	 * Apply processing and build a complete {@link ConfigurationClass} by reading the
	 * annotations, members and methods from the source class. This method can be called
	 * multiple times as relevant sources are discovered.
	 * @param configClass the configuration class being build
	 * @param sourceClass a source class
	 * @return the superclass, or {@code null} if none found or previously processed
	 */
	@Nullable
	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
        // 这里是根据启动类@ComponentScan注解来扫描项目中的bean
		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
                //遍历项目中的bean,如果是注解定义的bean,则进一步解析
				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)) {
                        //递归解析,所有的bean,如果有注解,会进一步解析注解中包含的bean
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		// Process any @Import annotations
        //递归解析,获取导入的配置类,很多情况下,导入的配置类中会同样包含导入类注解
		processImports(configClass, sourceClass, getImports(sourceClass), true);

		// Process any @ImportResource annotations
        //解析@ImportResource配置类
		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
        //处理@Bean注解修饰的类
		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;
	}
11、获取配置类的逻辑
processImports(configClass, sourceClass, getImports(sourceClass), true);

	/**
	 * Returns {@code @Import} class, considering all meta-annotations.
	 */
	private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
		Set<SourceClass> imports = new LinkedHashSet<>();
		Set<SourceClass> visited = new LinkedHashSet<>();
		collectImports(sourceClass, imports, visited);
		return imports;
	}
------------------
    	/**
	 * Recursively collect all declared {@code @Import} values. Unlike most
	 * meta-annotations it is valid to have several {@code @Import}s declared with
	 * different values; the usual process of returning values from the first
	 * meta-annotation on a class is not sufficient.
	 * <p>For example, it is common for a {@code @Configuration} class to declare direct
	 * {@code @Import}s in addition to meta-imports originating from an {@code @Enable}
	 * annotation.
	 * 看到所有的bean都以导入的方式被加载进去
	 */
	private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
			throws IOException {

		if (visited.add(sourceClass)) {
			for (SourceClass annotation : sourceClass.getAnnotations()) {
				String annName = annotation.getMetadata().getClassName();
				if (!annName.equals(Import.class.getName())) {
					collectImports(annotation, imports, visited);
				}
			}
			imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
		}
	}
12、ConfigurationClassParser中的parse方法中的最后一行,继续跟进该方法:
this.deferredImportSelectorHandler.process()
-------------
public void process() {
			List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
			this.deferredImportSelectors = null;
			try {
				if (deferredImports != null) {
					DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
					deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
					deferredImports.forEach(handler::register);
					handler.processGroupImports();
				}
			}
			finally {
				this.deferredImportSelectors = new ArrayList<>();
			}
		}
---------------
  public void processGroupImports() {
			for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
				grouping.getImports().forEach(entry -> {
					ConfigurationClass configurationClass = this.configurationClasses.get(
							entry.getMetadata());
					try {
						processImports(configurationClass, asSourceClass(configurationClass),
								asSourceClasses(entry.getImportClassName()), false);
					}
					catch (BeanDefinitionStoreException ex) {
						throw ex;
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to process import candidates for configuration class [" +
										configurationClass.getMetadata().getClassName() + "]", ex);
					}
				});
			}
		}
------------
    /**
		 * Return the imports defined by the group.
		 * @return each import with its associated configuration class
		 */
		public Iterable<Group.Entry> getImports() {
			for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
				this.group.process(deferredImport.getConfigurationClass().getMetadata(),
						deferredImport.getImportSelector());
			}
			return this.group.selectImports();
		}
	}
------------
    public DeferredImportSelector getImportSelector() {
			return this.importSelector;
		}
------------
    @Override
		public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
			Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
					() -> String.format("Only %s implementations are supported, got %s",
							AutoConfigurationImportSelector.class.getSimpleName(),
							deferredImportSelector.getClass().getName()));
			AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
					.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
			this.autoConfigurationEntries.add(autoConfigurationEntry);
			for (String importClassName : autoConfigurationEntry.getConfigurations()) {
				this.entries.putIfAbsent(importClassName, annotationMetadata);
			}
		}

  • 13
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值