springboot解析bean原理

Springboot

首先创建一个spring-boot项目

@SpringBootApplication
public class GeliqiuApplication {

    public static void main(String[] args) {
        SpringApplication.run(GeliqiuApplication.class, args);
    }

}

点击run方法进入内部

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
	return run(new Class<?>[] { primarySource }, args);
}
	//1.继续进入
	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}
	//2.进入new SpringApplication(primarySources)
	public SpringApplication(Class<?>... primarySources) {
		this(null, primarySources);
	}

	/**
	 * Create a new {@link SpringApplication} instance. The application context will load
	 * beans from the specified primary sources (see {@link SpringApplication class-level}
	 * documentation for details. The instance can be customized before calling
	 * {@link #run(String...)}.
	 * @param resourceLoader the resource loader to use
	 * @param primarySources the primary bean sources
	 * @see #run(Class, String[])
	 * @see #setSources(Set)
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		//保存启动类
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		//web类型,引入spring-web之后会返回WebApplicationType.SERVLET
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}
	//3.退出步骤2,进入步骤1方法下的.run(args);

进入run方法后:

/**
 *注释也说了,运行spring application后,创建和更新容器
 * Run the Spring application, creating and refreshing a new
 * {@link ApplicationContext}.
 * @param args the application arguments (usually passed from a Java main method)
 * @return a running {@link ApplicationContext}
 */
public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   DefaultBootstrapContext bootstrapContext = createBootstrapContext();
   ConfigurableApplicationContext context = null;
   configureHeadlessProperty();
   //1.获取监听器
   SpringApplicationRunListeners listeners = getRunListeners(args);
   listeners.starting(bootstrapContext, this.mainApplicationClass);
   try {
      //2.准备环境参数
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
      ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
      configureIgnoreBeanInfo(environment);
      //准备banner字体打印,估计就是Spring LOGO
      Banner printedBanner = printBanner(environment);
      //3.创建Spring容器
      context = createApplicationContext();
      context.setApplicationStartup(this.applicationStartup);
      //4.Spring容器前置处理
      prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
      //5.刷新容器(会进入spring核心方法refresh())
      refreshContext(context);
      //6.spring后置处理
      afterRefresh(context, applicationArguments);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
      }
      //7.发出容器启动事件
      listeners.started(context);
      //8.调用runners,比如CommandLineRunner.class的子类等等,这样可以在容器启动之后便执行方法
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, listeners);
      throw new IllegalStateException(ex);
   }

   try {
      listeners.running(context);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, null);
      throw new IllegalStateException(ex);
   }
   //返回容器
   return context;
}

1.获取监听器

在这里插入图片描述

进入starting方法

void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
  //启动监听器
   doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
         (step) -> {
            if (mainApplicationClass != null) {
               step.tag("mainApplicationClass", mainApplicationClass.getName());
            }
         });
}
	//再次进入同名listener.starting(bootstrapContext),会看到一个广播器,启动start时间下的多个监听器,如LoggingApplicationListener等
	@Override
	public void starting(ConfigurableBootstrapContext bootstrapContext) {
		this.initialMulticaster
				.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
	}

在这里插入图片描述

2.准备环境参数

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
//准备banner字体打印,估计就是Spring LOGO
Banner printedBanner = printBanner(environment);

这个步骤主要保存了main函数的参数args,并且创建了SERVLE环境

3.创建Spring容器

步骤3主要根据web类型创建了一个容器ApplicationContext

protected ConfigurableApplicationContext createApplicationContext() {
   return this.applicationContextFactory.create(this.webApplicationType);
}
	//进入create方法,会来到本段代码的最会一行
	/**
	 * A default {@link ApplicationContextFactory} implementation that will create an
	 * appropriate context for the {@link WebApplicationType}.
	 */
	ApplicationContextFactory DEFAULT = (webApplicationType) -> {
		try {
			switch (webApplicationType) {
			case SERVLET:
				return new AnnotationConfigServletWebServerApplicationContext();
			case REACTIVE:
				return new AnnotationConfigReactiveWebServerApplicationContext();
			default:
				return new AnnotationConfigApplicationContext();
			}
		}
		catch (Exception ex) {
			throw new IllegalStateException("Unable create a default ApplicationContext instance, "
					+ "you may need a custom ApplicationContextFactory", ex);
		}
	};

	/**
	 * 上方有一个默认的实现方法,由于我们的web服务是servlet,所以创建的就是 AnnotationConfigServletWebServerApplicationContext
	 * Creates the {@link ConfigurableApplicationContext application context} for a
	 * {@link SpringApplication}, respecting the given {@code webApplicationType}.
	 * @param webApplicationType the web application type
	 * @return the newly created application context
	 */
	ConfigurableApplicationContext create(WebApplicationType webApplicationType);

4.准备容器

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
   //设置容器的各种变量
   context.setEnvironment(environment);
   //给容器添加后置处理
   postProcessApplicationContext(context);
   //执行各个initialiizer的初始化操作
   applyInitializers(context);
   //发布容器已经准备好了的事件
   listeners.contextPrepared(context);
   bootstrapContext.close(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
   //获取我们的启动类 MyApplication.class
   Set<Object> sources = getAllSources();
   Assert.notEmpty(sources, "Sources must not be empty");
   //加载启动类,将启动类注入容器
   load(context, sources.toArray(new Object[0]));
   //通知监听器,容器已经加载
   listeners.contextLoaded(context);
}

load(context, sources.toArray(new Object[0]));可以看到下图,在没有加载启动类时,容器beanDefinitionMap中并没有启动类
在这里插入图片描述

执行load方法过后启动类加载到容器中

在这里插入图片描述

5.刷新容器(spring核心)

进入run方法下的AbstractApplicationContext.class 下的refreshContext(context);方法后,springboot就会将任务交给spring进行处理。

点击进入内部的refresh()

注意下方的ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();如果是以xml的形式配置的bean,则是在此处读取出相关的标签,转化为对bean的描述的beanDefinition并加入容器中。但是,我们的springboot加载的bean,如@Componnet等注解注入的bean却不是在此处,而是在下方的invokeBeanFactoryPostProcessors(beanFactory);

	@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.
			//创建BeanFactory,在这一步中添加读取xml文件,构建BeanDefinition(springboot无需重点关注)
			/**
			 *点击进入该方法,{@link #refreshBeanFactory()}
			 *进入{@link AbstractRefreshableApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)} 	}
			 * 之后一直深入里面的方法,不断点击loadBean之类的方法,再之后parseElement之类的方法,然后点击register之类的方法,最后会发现
			 * 进入{@link org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition(BeanDefinitionHolder, BeanDefinitionRegistry)}
			 * 再进入{@link DefaultListableBeanFactory#registerBeanDefinition(String, BeanDefinition)}
			 * 会在这个方法中把BeanDefinition加入容器当中
			 * 	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
			 */
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//准备相关内容,如ClassLoader ,beanProcessor,registerResolvableDependency等等内容
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.

				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
        //springboot在此进行bean的解析(需要关注)
				//根据不同的PostProcessors order顺序执行不同的bean处理
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				/**
				 * 完成ioc、di和aop(IOC重点)
				 * 创建所有的bean(非lazy-init)
				 */
				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

执行obtainFreshBeanFactory()后,并没有自己注入的业务类

在这里插入图片描述

进入invokeBeanFactoryPostProcessors(beanFactory);方法

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
	//···略···
	}
//进入invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())

	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
	//···略···
    			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
    	//进入该方法
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();
  //···略···
    
  }

	/**
	 *调用处理器获得bean
	 * Invoke the given BeanDefinitionRegistryPostProcessor beans.
	 */
	private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
	}
	//进入
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
	//再进入ConfigurationClassPostProcessor.class下的方法
	/**
	 * Derive further bean definitions from the configuration classes in the registry.
	 */
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		int registryId = System.identityHashCode(registry);
		if (this.registriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
		}
		if (this.factoriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + registry);
		}
		this.registriesPostProcessed.add(registryId);

		processConfigBeanDefinitions(registry);
	}

进入processConfigBeanDefinitions(registry);

来到较为靠下的部分,找到这部分代码

		do {
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
      //解析
			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);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

			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());

进入parser.parse(candidates)

	public void parse(Set<BeanDefinitionHolder> configCandidates) {
		this.deferredImportSelectors = new LinkedList<>();

		for (BeanDefinitionHolder holder : configCandidates) {
			BeanDefinition bd = holder.getBeanDefinition();
			//根据BeanDefinition类型进行相应的解析
			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);
			}
		}

		processDeferredImportSelectors();
	}

再进入parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName())

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 {
			//解析
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);
		//解析完之后的结果保存
		this.configurationClasses.put(configClass, configClass);
	}

进入sourceClass = doProcessConfigurationClass(configClass, sourceClass),主要看ComponentScan解析那段

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
      throws IOException {
  //···略···
  		// Process any @ComponentScan annotations
		//根据@ComponentScan扫描需要注入容器的类(比较常见的controller、service等)
		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());
					}
				}
			}
		}
  //···略···
}

//再进入this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName())
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
	//省略上方准备的所有代码
  //扫描包下的class
  return scanner.doScan(StringUtils.toStringArray(basePackages));
}

进入扫描方法doScan(StringUtils.toStringArray(basePackages)),注释也说了,这个方法的主要内容是扫描包下符合的class,并且返回beanDefinition对象

/**
 * Perform a scan within the specified base packages,
 * returning the registered bean definitions.
 * <p>This method does <i>not</i> register an annotation config processor
 * but rather leaves this up to the caller.
 * @param basePackages the packages to check for annotated classes
 * @return set of beans registered if any for tooling registration purposes (never {@code null})
 */
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   Assert.notEmpty(basePackages, "At least one base package must be specified");
   Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
   for (String basePackage : basePackages) {
      //找到自己注入容器的类,创建对应的BeanDefinition
      Set<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) {
            //解析bean的属性,@DependsOn、@Lazy、@Primary等
            AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
         }
         if (checkCandidate(beanName, candidate)) {
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
            definitionHolder =
                  AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}

进入Set<BeanDefinition> candidates = findCandidateComponents(basePackage),然后再进入scanCandidateComponents(basePackage)

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
   Set<BeanDefinition> candidates = new LinkedHashSet<>();
   try {
      // classpath*:com/com/geye/geliqiu.**/*.class 扫描启动类所在的包及子包下的class文件
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
            resolveBasePackage(basePackage) + '/' + this.resourcePattern;
     //扫描包下的class
      Resource[] resources = getResourcePatternResolver().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 = getMetadataReaderFactory().getMetadataReader(resource);
               //isCandidateComponent(metadataReader)筛选出符合@Componnet标记的class
               if (isCandidateComponent(metadataReader)) {
                  //创建一个ScannedGenericBeanDefinition类型的beanDefinition
                  ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                  sbd.setSource(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;
}

扫描包下面的所有的.class文件

在这里插入图片描述

过滤需要注入容器的业务类

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
   for (TypeFilter tf : this.excludeFilters) {
      if (tf.match(metadataReader, getMetadataReaderFactory())) {
         return false;
      }
   }
   //筛选出符合@Component标记的类
   for (TypeFilter tf : this.includeFilters) {
      if (tf.match(metadataReader, getMetadataReaderFactory())) {
         return isConditionMatch(metadataReader);
      }
   }
   return false;
}

可以看到这里有几个用于筛选的过滤器,只有符合@Component注解标注的类才会返回true,像我们常见的@RestController@Controller@Service内部都是使用了@Component标识,所以会符合条件。

在这里插入图片描述

筛选出对应的class之后,创建ScannedGenericBeanDefinition然后添加到candidates中返回,在再返回到doScan方法中,设置相应的参数。
咋们再回到之前的refresh方法下,这个是还没有执行invokeBeanFactoryPostProcessors(beanFactory)的样子
在这里插入图片描述

再看一下执行之后的样子,里面有了注入了自己的业务类
在这里插入图片描述

至此,业务中注入bean到容器转化为beanDefinition的过程就结束了。

至于IOC、AOP等内容可自行百度

总结:

springboot解析bean的整个流程:

  1. 创建SpringApplication
  2. 执行run方法
  3. 创建容器context
  4. 刷新容器refreshContext(context)springboot将工作交给spring
  5. 调用工厂处理器invokeBeanFactoryPostProcessors(beanFactory)
  6. 使用ConfigurationClassPostProcessor.class内的processConfigBeanDefinitions解析方法
  7. 再解析ComponentScan扫描下的class
  8. 最后ClassPathBeanDefinitionScanner下的protected Set<BeanDefinitionHolder> doScan(String... basePackages)扫描包下的class,并筛选出@Component标记的class
  9. 创建符合条件的class对应的BeanDefinition并返回

参考:

  1. spirngboot启动流程https://www.cnblogs.com/java-chen-hao/p/11829344.html
  2. spring ioc解析https://blog.csdn.net/zhanyu1/article/details/83023854
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值