Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
Spring Boot特点
1. 创建独立的Spring应用程序
2. 嵌入的Tomcat,无需部署WAR文件
3. 简化Maven配置
4. 自动配置Spring
5. 提供生产就绪型功能,如指标,健康检查和外部配置
6. 绝对没有代码生成和对XML没有要求配置
安装Spring Boot
从最根本上来讲,Spring Boot就是一些库的集合,它能够被任意项目的构建系统所使用。简便起见,该框架也提供了命令行界面,它可以用来运行和测试Boot应用。框架的发布版本,包括集成的CLI(命令行界面),可以在Spring仓库中手动下载和安装。一种更为简便的方式是使用Groovy环境管理器(Groovy enVironment Manager,GVM),它会处理Boot版本的安装和管理。Boot及其CLI可以通过GVM的命令行gvm install springboot进行安装。在OS X上安装Boot可以使用Homebrew包管理器。为了完成安装,首先要使用brew tap pivotal/tap切换到Pivotal仓库中,然后执行brew install springboot命令。
要进行打包和分发的工程会依赖于像 Maven或 Gradle这样的构建系统。为了简化依赖图,Boot的功能是模块化的,通过导入Boot所谓的“starter”模块,可以将许多的依赖添加到工程之中。为了更容易地管理依赖版本和使用默认配置,框架提供了一个parent POM,工程可以继承它。
SpringBoot 知识点汇总
SpringBoot 自动配置的原理?
首先自动配置是配置spring-boot-autoconfigure-2.0.4.RELEASE.jar包下MATA-INF下的spring.properties 文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration所对应自动配置类。
其次springBoot启动类中的@springBootApplication隐含的引入了EnableAutoConfigurationImportSelector;
- // 注解链
- @SpringBootApplication
- => @EnableAutoConfiguration
- => @Import(EnableAutoConfigurationImportSelector.class)
在SpringApplication的run方法中,会调context = createApplicationContext();在实例化这个ConfigurableApplicationContext时,不管是AnnotationConfigEmbeddedWebApplicationContext或AnnotationConfigApplicationContext时(这两个类是专门处理Spring注解方式配置的容器,直接依赖于注解作为容器配置信息来源的IoC容器。 AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的web版本,两者的用法以及对注解的处理方式几乎没有什么差别),都会实例化一个AnnotatedBeanDefinitionReader。例如AnnotationConfigEmbeddedWebApplicationContext实例化代码:
- public AnnotationConfigEmbeddedWebApplicationContext() {
- this.reader = new AnnotatedBeanDefinitionReader(this);
- this.scanner = new ClassPathBeanDefinitionScanner(this);
- }
-
这里将构造AnnotatedBeanDefinitionReader,在AnnotatedBeanDefinitionReader实例化过程中,会向beanFactory注册CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor、ConfigurationClassPostProcessor等:
- public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
- Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
- Assert.notNull(environment, "Environment must not be null");
- this.registry = registry;
- this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
- AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
- }
- public static Set registerAnnotationConfigProcessors(
- BeanDefinitionRegistry registry, Object source) {
-
- DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
- if (beanFactory != null) {
- if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
- beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
- }
- if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
- beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
- }
- }
-
- Set beanDefs = new LinkedHashSet(4);
-
- if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
- RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
- def.setSource(source);
- beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
- }
-
- if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
- RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
- def.setSource(source);
- beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
- }
-
- if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
- RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
- def.setSource(source);
- beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
- }
-
- // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
- if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
- RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
- def.setSource(source);
- beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
- }
-
- // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
- if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
- RootBeanDefinition def = new RootBeanDefinition();
- try {
- def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
- AnnotationConfigUtils.class.getClassLoader()));
- }
- catch (ClassNotFoundException ex) {
- throw new IllegalStateException(
- "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
- }
- def.setSource(source);
- beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
- }
-
- if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
- RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
- def.setSource(source);
- beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
- }
- if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
- RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
- def.setSource(source);
- beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
- }
-
- return beanDefs;
- }
也就是说createApplicationContext()完后,beanFactory的beanDefinitionMap会有6个值。
SpringApplication的run方法中,在调用createApplicationContext();后会调用prepareContext(context, environment, listeners, applicationArguments,printedBanner):
- private void prepareContext(ConfigurableApplicationContext context,
- ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
- ApplicationArguments applicationArguments, Banner printedBanner) {
- // ….
- // Load the sources
- Set sources = getSources();
- Assert.notEmpty(sources, "Sources must not be empty");
- load(context, sources.toArray(new Object[sources.size()]));
- listeners.contextLoaded(context);
- }
getSources()返回的就是new SpringApplication(Application.class)传入的参数,即我们的主类,然后调用了load()方法,在load()中会生成BeanDefinitionLoader实例,并把主类注册到IOC容器中。
OK,到这里即在调用我们熟悉的AbstractApplicationContext#refresh()前,beanFactory有7个定义好的beanDefinition。
- public void refresh() throws BeansException, IllegalStateException {
- Object var1 = this.startupShutdownMonitor;
- synchronized(this.startupShutdownMonitor) {
- this.prepareRefresh();
- ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
- this.prepareBeanFactory(beanFactory);
-
- try {
- this.postProcessBeanFactory(beanFactory);
- this.invokeBeanFactoryPostProcessors(beanFactory);
- this.registerBeanPostProcessors(beanFactory);
- this.initMessageSource();
- this.initApplicationEventMulticaster();
- this.onRefresh();
- this.registerListeners();
- this.finishBeanFactoryInitialization(beanFactory);
- this.finishRefresh();
- } catch (BeansException var9) {
- if (this.logger.isWarnEnabled()) {
- this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
- }
-
- this.destroyBeans();
- this.cancelRefresh(var9);
- throw var9;
- } finally {
- this.resetCommonCaches();
- }
-
- }
- }
ConfigurationClassPostProcessor是BeanFactoryPostProcessor的子类,会在Spring容器refresh时,invokeBeanFactoryPostProcessors(beanFactory)方法中调用到。ConfigurationClassPostProcessor会解析到我们的主类,把@Import中的类拿出来,调用它的selectImports()方法。
ConfigurationClassPostProcessor 中ConfigurationClassParser分析配置类时,如果发现注@Import(ImportSelector)的情况,就会创建一个相应的ImportSelector对象, 并调用其方法 public String[] selectImports(AnnotationMetadata annotationMetadata), 这里 EnableAutoConfigurationImportSelector的导入@Import(EnableAutoConfigurationImportSelector.class) 就属于这种情况,所以ConfigurationClassParser会实例化一个 EnableAutoConfigurationImportSelector 并调用它的 selectImports() 方法。
- 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);
- } else if (this.factoriesPostProcessed.contains(registryId)) {
- throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
- } else {
- this.registriesPostProcessed.add(registryId);
- this.processConfigBeanDefinitions(registry);
- }
- } //BeanFactoryPostProcessor接口唯一的方法,被ConfigurationClassPostProcessor实现了;
-
//该方法中对配置类中的@import中的类进行解析
- public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
- List configCandidates = new ArrayList();
- String[] candidateNames = registry.getBeanDefinitionNames();
- String[] var4 = candidateNames;
- int var5 = candidateNames.length;
-
- for(int var6 = 0; var6 < var5; ++var6) {
- String beanName = var4[var6];
- BeanDefinition beanDef = registry.getBeanDefinition(beanName);
- if (!ConfigurationClassUtils.isFullConfigurationClass(beanDef) && !ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
- if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
- configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
- }
- } else if (this.logger.isDebugEnabled()) {
- this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
- }
- }
-
- if (!configCandidates.isEmpty()) {
- configCandidates.sort((bd1, bd2) -> {
- int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
- int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
- return Integer.compare(i1, i2);
- });
- SingletonBeanRegistry sbr = null;
- if (registry instanceof SingletonBeanRegistry) {
- sbr = (SingletonBeanRegistry)registry;
- if (!this.localBeanNameGeneratorSet) {
- BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
- if (generator != null) {
- this.componentScanBeanNameGenerator = generator;
- this.importBeanNameGenerator = generator;
- }
- }
- }
-
- if (this.environment == null) {
- this.environment = new StandardEnvironment();
- }
-
- ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
- Set candidates = new LinkedHashSet(configCandidates);
- HashSet alreadyParsed = new HashSet(configCandidates.size());
-
- do {
- parser.parse(candidates);
- parser.validate();
- Set configClasses = new LinkedHashSet(parser.getConfigurationClasses());
- configClasses.removeAll(alreadyParsed);
- 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 oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
- Set alreadyParsedClasses = new HashSet();
- Iterator var12 = alreadyParsed.iterator();
-
- while(var12.hasNext()) {
- ConfigurationClass configurationClass = (ConfigurationClass)var12.next();
- alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
- }
-
- String[] var23 = newCandidateNames;
- int var24 = newCandidateNames.length;
-
- for(int var14 = 0; var14 < var24; ++var14) {
- String candidateName = var23[var14];
- 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());
-
- if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
- sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
- }
-
- if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
- ((CachingMetadataReaderFactory)this.metadataReaderFactory).clearCache();
- }
-
- }
- }
- public void parse(Set configCandidates) {
- this.deferredImportSelectors = new LinkedList();
- Iterator var2 = configCandidates.iterator();
-
- while(var2.hasNext()) {
- BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
- BeanDefinition bd = holder.getBeanDefinition();
-
- try {
- if (bd instanceof AnnotatedBeanDefinition) {
- this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
- } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
- this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
- } else {
- this.parse(bd.getBeanClassName(), holder.getBeanName());
- }
- } catch (BeanDefinitionStoreException var6) {
- throw var6;
- } catch (Throwable var7) {
- throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
- }
- }
-
- this.processDeferredImportSelectors();
- }
- private void processDeferredImportSelectors() {
- List deferredImports = this.deferredImportSelectors;
- this.deferredImportSelectors = null;
- if (deferredImports != null) {
- deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
- Map groupings = new LinkedHashMap();
- Map configurationClasses = new HashMap();
- Iterator var4 = deferredImports.iterator();
-
- while(var4.hasNext()) {
- ConfigurationClassParser.DeferredImportSelectorHolder deferredImport = (ConfigurationClassParser.DeferredImportSelectorHolder)var4.next();
- Class extends Group> group = deferredImport.getImportSelector().getImportGroup();
- ConfigurationClassParser.DeferredImportSelectorGrouping grouping = (ConfigurationClassParser.DeferredImportSelectorGrouping)groupings.computeIfAbsent(group != null ? group : deferredImport, (key) -> {
- return new ConfigurationClassParser.DeferredImportSelectorGrouping(this.createGroup(group));
- });
- grouping.add(deferredImport);
- configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getConfigurationClass());
- }
-
- var4 = groupings.values().iterator();
-
- while(var4.hasNext()) {
- ConfigurationClassParser.DeferredImportSelectorGrouping grouping = (ConfigurationClassParser.DeferredImportSelectorGrouping)var4.next();
- grouping.getImports().forEach((entry) -> {
- ConfigurationClass configurationClass = (ConfigurationClass)configurationClasses.get(entry.getMetadata());
-
- try {
- this.processImports(configurationClass, this.asSourceClass(configurationClass), this.asSourceClasses(entry.getImportClassName()), false); //调用processImports方法
- } catch (BeanDefinitionStoreException var5) {
- throw var5;
- } catch (Throwable var6) {
- throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configurationClass.getMetadata().getClassName() + "]", var6);
- }
- });
- }
-
- }
- }
- private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass, Collection importCandidates, boolean checkForCircularImports) {
- if (!importCandidates.isEmpty()) {
- if (checkForCircularImports && this.isChainedImportOnStack(configClass)) {
- this.problemReporter.error(new ConfigurationClassParser.CircularImportProblem(configClass, this.importStack));
- } else {
- this.importStack.push(configClass);
-
- try {
- Iterator var5 = importCandidates.iterator();
-
- while(true) {
- while(true) {
- while(var5.hasNext()) {
- ConfigurationClassParser.SourceClass candidate = (ConfigurationClassParser.SourceClass)var5.next();
- Class candidateClass;
- if (candidate.isAssignable(ImportSelector.class)) {
- candidateClass = candidate.loadClass();
- ImportSelector selector = (ImportSelector)BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
- ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);
- if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
- this.deferredImportSelectors.add(new ConfigurationClassParser.DeferredImportSelectorHolder(configClass, (DeferredImportSelector)selector));
- } else {
- String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); //执行@import类的selectImports方法;
- Collection importSourceClasses = this.asSourceClasses(importClassNames);
- this.processImports(configClass, currentSourceClass, importSourceClasses, false);
- }
- } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
- candidateClass = candidate.loadClass();
- ImportBeanDefinitionRegistrar registrar = (ImportBeanDefinitionRegistrar)BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
- ParserStrategyUtils.invokeAwareMethods(registrar, this.environment, this.resourceLoader, this.registry);
- configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
- } else {
- this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
- this.processConfigurationClass(candidate.asConfigClass(configClass));
- }
- }
-
- return;
- }
- }
- } catch (BeanDefinitionStoreException var15) {
- throw var15;
- } catch (Throwable var16) {
- throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configClass.getMetadata().getClassName() + "]", var16);
- } finally {
- this.importStack.pop();
- }
- }
- }
- }
- // selectImports 的具体执行逻辑 注释参考https://blog.csdn.net/andy_zhang2007/article/details/78580980
- @Override
- public String[] selectImports(AnnotationMetadata annotationMetadata) {
- if (!isEnabled(annotationMetadata)) {
- return NO_IMPORTS;
- }
- try {
- // 从配置文件中加载 AutoConfigurationMetadata
- AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
- .loadMetadata(this.beanClassLoader);
- AnnotationAttributes attributes = getAttributes(annotationMetadata);
- // 获取所有候选配置类EnableAutoConfiguration
- // 使用了内部工具使用SpringFactoriesLoader,查找classpath上所有jar包中的
- // META-INFspring.factories,找出其中key为
- // org.springframework.boot.autoconfigure.EnableAutoConfiguration
- // 的属性定义的工厂类名称。
- // 虽然参数有annotationMetadata,attributes,但在 AutoConfigurationImportSelector 的
- // 实现 getCandidateConfigurations()中,这两个参数并未使用
- List configurations = getCandidateConfigurations(annotationMetadata,
- attributes);
- // 去重
- configurations = removeDuplicates(configurations);
- // 排序 : 先按字典序,再按order属性,再考虑注解 @AutoConfigureBefore @AutoConfigureAfter
- configurations = sort(configurations, autoConfigurationMetadata);
- // 应用 exclusion 属性
- Set exclusions = getExclusions(annotationMetadata, attributes);
- checkExcludedClasses(configurations, exclusions);
- configurations.removeAll(exclusions);
- // 应用过滤器AutoConfigurationImportFilter,
- // 对于 spring boot autoconfigure,定义了一个需要被应用的过滤器 :
- // org.springframework.boot.autoconfigure.condition.OnClassCondition,
- // 此过滤器检查候选配置类上的注解@ConditionalOnClass,如果要求的类在classpath
- // 中不存在,则这个候选配置类会被排除掉
- configurations = filter(configurations, autoConfigurationMetadata);
- // 现在已经找到所有需要被应用的候选配置类
- // 广播事件 AutoConfigurationImportEvent
- fireAutoConfigurationImportEvents(configurations, exclusions);
- return configurations.toArray(new String[configurations.size()]);
- }
- catch (IOException ex) {
- throw new IllegalStateException(ex);
- }
- }
- /**
- * Return the auto-configuration class names that should be considered. By default
- * this method will load candidates using SpringFactoriesLoader with
- * getSpringFactoriesLoaderFactoryClass().
- * @param metadata the source metadata
- * @param attributes the getAttributes(AnnotationMetadata) annotation
- * attributes
- * @return a list of candidate configurations
- */
- protected List getCandidateConfigurations(AnnotationMetadata metadata,
- AnnotationAttributes attributes) {
- List 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;
- }
- /**
- * Return the class used by SpringFactoriesLoader to load configuration
- * candidates.
- * @return the factory class
- */
- protected Class> getSpringFactoriesLoaderFactoryClass() {
- return EnableAutoConfiguration.class;
- }
- /**
- * 根据autoConfigurationMetadata信息对候选配置类configurations进行过滤
- **/
- private List filter(List configurations,
- AutoConfigurationMetadata autoConfigurationMetadata) {
- long startTime = System.nanoTime();
- String[] candidates = configurations.toArray(new String[configurations.size()]);
- // 记录候选配置类是否需要被排除,skip为true表示需要被排除,全部初始化为false,不需要被排除
- boolean[] skip = new boolean[candidates.length];
- // 记录候选配置类中是否有任何一个候选配置类被忽略,初始化为false
- boolean skipped = false;
- // 获取AutoConfigurationImportFilter并逐个应用过滤
- for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
- // 对过滤器注入其需要Aware的信息
- invokeAwareMethods(filter);
- // 使用此过滤器检查候选配置类跟autoConfigurationMetadata的匹配情况
- boolean[] match = filter.match(candidates, autoConfigurationMetadata);
- for (int i = 0; i < match.length; i++) {
- if (!match[i]) {
- // 如果有某个候选配置类不符合当前过滤器,将其标记为需要被排除,
- // 并且将 skipped设置为true,表示发现了某个候选配置类需要被排除
- skip[i] = true;
- skipped = true;
- }
- }
- }
- if (!skipped) {
- // 如果所有的候选配置类都不需要被排除,则直接返回外部参数提供的候选配置类集合
- return configurations;
- }
- // 逻辑走到这里因为skipped为true,表明上面的的过滤器应用逻辑中发现了某些候选配置类
- // 需要被排除,这里排除那些需要被排除的候选配置类,将那些不需要被排除的候选配置类组成
- // 一个新的集合返回给调用者
- List result = new ArrayList(candidates.length);
- for (int i = 0; i < candidates.length; i++) {
- if (!skip[i]) {
- result.add(candidates[i]);
- }
- }
- if (logger.isTraceEnabled()) {
- int numberFiltered = configurations.size() - result.size();
- logger.trace("Filtered " + numberFiltered + " auto configuration class in "
- + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)
- + " ms");
- }
- return new ArrayList(result);
- }
- /**
- * 使用内部工具 SpringFactoriesLoader,查找classpath上所有jar包中的
- * META-INFspring.factories,找出其中key为
- * org.springframework.boot.autoconfigure.AutoConfigurationImportFilter
- * 的属性定义的过滤器类并实例化。
- * AutoConfigurationImportFilter过滤器可以被注册到 spring.factories用于对自动配置类
- * 做一些限制,在这些自动配置类的字节码被读取之前做快速排除处理。
- * spring boot autoconfigure 缺省注册了一个 AutoConfigurationImportFilter :
- * org.springframework.boot.autoconfigure.condition.OnClassCondition
- **/
- protected List getAutoConfigurationImportFilters() {
- return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class,
- this.beanClassLoader);
- }
- protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
- List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
- }
- public static List loadFactoryNames(Class> factoryClass, @Nullable ClassLoader classLoader) {
- String factoryClassName = factoryClass.getName();
- return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
- }
- private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) {
- MultiValueMap result = (MultiValueMap)cache.get(classLoader);
- if (result != null) {
- return result;
- } else {
- try {
- Enumeration urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
- LinkedMultiValueMap result = new LinkedMultiValueMap();
-
- while(urls.hasMoreElements()) {
- URL url = (URL)urls.nextElement();
- UrlResource resource = new UrlResource(url);
- Properties properties = PropertiesLoaderUtils.loadProperties(resource);
- Iterator var6 = properties.entrySet().iterator();
-
- while(var6.hasNext()) {
- Entry, ?> entry = (Entry)var6.next();
- List factoryClassNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));
- result.addAll((String)entry.getKey(), factoryClassNames);
- }
- }
-
- cache.put(classLoader, result);
- return result;
- } catch (IOException var9) {
- throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var9);
- }
- }
- }
而loadSpringFactories会扫描所有jar包下的 META‐INF/spring.factories文件,并封装成properties属性对象;并以key-value的形式存放在MultiValueMap对象中,List configurations = getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置时,只需要获取key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的list保存的value,然后返回到processImports方法中,最终注册到IOC容器中;整个自动配置结束;