SpringBoot 1.x 之入门

1 SpringBoot简介

  • SpringBoot简化Spring应用开发,约定大于配置,去繁从简,just run就能创建一个独立的,产品级别的应用。
  • 背景:
    • J2EE笨重的开发、繁多的配置、低下的开发效率、复杂的部署流程、第三方技术集成难度大。
  • 解决:
    • “Spring全家桶”时代。
    • SpringBoot-->J2EE一站式解决方案。
    • SpringCloud-->分布式整体解决方案。  
  • 优点:
    • 快速创建独立运行的Spring项目以及与主流框架集成。
    • 使用嵌入式的Servlet容器,应用无需打成war包。
    • starters自动依赖和版本控制。
    • 大量的自动配置,简化开发,也可以修改默认值。
    • 无需配置XML,无代码生成,开箱即用。
    • 准生产环境的运行时应用监控。
    • 与云计算的天然集成。  

SpringBoot 1.x 之入门_第1张图片

 

 

2 微服务简介

  • 2014年,Martin Fowler与James Lewis共同提出。
  • 微服务是一种架构风格(服务微化)。
  • 一个应用应该是一组小型服务,可以通过HTTP的方式进行互通。

 

  • 单体应用:ALL IN ONE。
  • 微服务:每一个功能元素最终都是一个可独立替换和独立升级的软件单元。

 

3 环境准备

  • JDK1.8。
  • Maven 3.x。
  • IntelliJ IDEA 2019.3。
  • SpringBoot 1.5.9.RELEASE。

 

  • Maven设置:
  • 给maven的settings.xml配置文件的profiles标签添加如下信息:
<profile> 
  <id>jdk‐1.8id>  
  <activation> 
    <activeByDefault>trueactiveByDefault>  
    <jdk>1.8jdk> 
  activation>  
  <properties> 
    <maven.compiler.source>1.8maven.compiler.source>  
    <maven.compiler.target>1.8maven.compiler.target>  
    <maven.compiler.compilerVersion>1.8maven.compiler.compilerVersion> 
  properties> 
profile>

 

4 SpringBoot-HelloWorld

4.1 创建Maven项目

  • 略。

4.2 导入SpringBoot相关的依赖

<parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-parentartifactId>
    <version>1.5.9.RELEASEversion>
parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
dependencies>

4.3 编写主程序,用来启动SpringBoot应用

  • 示例:
  • HelloWorldMainApplication.java
package com.sunxiaping;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication //标注一个主程序类,说明这是一个SpringBoot应用
public class HelloWorldMainApplication {
    public static void main(String[] args) {
        //SpringBoot应用启动起来
        SpringApplication.run(HelloWorldMainApplication.class,args);
    }
}

4.3 编写相关的Controller

  • 示例:
  • HelloWorldController.java
package com.sunxiaping.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloWorldController {

    @RequestMapping(value = "/hello")
    @ResponseBody
    public String hello() {
        return "helloWorld";
    }

}

4.4 运行主程序测试

  • 略。

4.5 简化部署

  • 在当前项目的pom.xml中添加如下的配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-maven-pluginartifactId>
        plugin>
    plugins>
build>
  • 将这个应用打成jar包,然后通过java -jar xxx.jar的命令进行执行。

 

5 HelloWorld探究

5.1 pom文件

5.1.1 父项目

<parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-parentartifactId>
    <version>1.5.9.RELEASEversion>
parent>

其父项目是

<parent> 
  <groupId>org.springframework.bootgroupId>  
  <artifactId>spring-boot-dependenciesartifactId>  
  <version>1.5.9.RELEASEversion>  
  <relativePath>../../spring-boot-dependenciesrelativePath> 
parent>

它是真正管理SpringBoot应用中的所有依赖版本,可以称之为SpringBoot的版本仲裁中心。
所以以后我们导入依赖默认是不需要写版本的,但是如果版本仲裁中心没有的,当然需要写版本号了。

5.1.2 启动器

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>

 

  • spring-boot-starter:SpringBoot的场景启动器。
  • spring-boot-starter-web:帮助我们导入了web模块正常运行所依赖的组件。

 

  • SpringBoot将所有的功能场景都抽取出来,做成一个个的starters(启动器),所以我们只需要在项目里引入这些starter,相关场景的所有依赖都会导入进来。
  • 要用什么功能就导入什么场景的启动器。

 5.2 主程序类、主入口

  • 示例:
package com.sunxiaping;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication //标注一个主程序类,说明这是一个SpringBoot应用
public class HelloWorldMainApplication {
    public static void main(String[] args) {
        //SpringBoot应用启动起来
        SpringApplication.run(HelloWorldMainApplication.class,args);
    }
}
  • @SpringBootApplication注解标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就能运行这个类的main方法来启动SpringBoot应用。
package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

    
    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
    Class[] exclude() default {};

    
    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
    String[] excludeName() default {};

    
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};

    
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    Class[] scanBasePackageClasses() default {};

}
  • @SpringBootConfiguration注解:标注在某个类上,就表明这是一个SpringBoot的配置类,其源码如下所示:
package org.springframework.boot;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.Configuration;


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

}
  • @Configuration注解,表明这是一个配置类,相当于原来xml格式的applicationContext.xml文件。配置类也是容器中的一个组件,其实@Configuration注解就是@Component注解,其源码如下所示:
package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {

    
    String value() default "";

}

 

  • @EnableAutoConfiguration注解:开启自动配置功能。以前我们需要配置的东西,SpringBoot帮我们自动配置。@EnableAutoConfiguration注解告诉SpringBoot开启自动配置功能,这样自动配置才能生效。其源码如下:
package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.support.SpringFactoriesLoader;


@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    
    Class[] exclude() default {};

    
    String[] excludeName() default {};

}
  • 其中,@AutoConfigurationPackage注解,是自动配置包的意思,其源码如下:
package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.Import;


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

}
  • 从源码中,我们可以看出@AutoConfigurationPackage注解会导入AutoConfigurationPackages.Registrar.class组件,其源码如下:
    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

        @Override
        public void registerBeanDefinitions(AnnotationMetadata metadata,
                BeanDefinitionRegistry registry) {
       //将当前标注注解类的包下的所有组件注册到Spring容器中  register(registry,
new PackageImport(metadata).getPackageName()); } @Override public Set determineImports(AnnotationMetadata metadata) { return Collections.singleton(new PackageImport(metadata)); } }
  • 所以,@SpringBootApplication注解的作用就是将其所在包以及子包下的所有组件都注册到SpringBoot中。
  • 其中,@Import(AutoConfigurationPackages.Registrar.class)将给容器中导入组件,其源码如下所示:
package org.springframework.boot.autoconfigure;

import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.type.AnnotationMetadata;


@Deprecated
public class EnableAutoConfigurationImportSelector
        extends AutoConfigurationImportSelector {

    @Override
    protected boolean isEnabled(AnnotationMetadata metadata) {
        if (getClass().equals(EnableAutoConfigurationImportSelector.class)) {
            return getEnvironment().getProperty(
                    EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,
                    true);
        }
        return true;
    }

}
  • 从上面的源码中,我们可以看到EnableAutoConfigurationImportSelector类继承了AutoConfigurationImportSelector,我们知道xxxImportSelector将会将所有需要导入的组件以全类名的方式返回,而这些组件就会被添加到容器中,我们需要查看AutoConfigurationImportSelector的源代码,如下所示:
package org.springframework.boot.autoconfigure;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;


public class AutoConfigurationImportSelector
        implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
        BeanFactoryAware, EnvironmentAware, Ordered {

    private static final String[] NO_IMPORTS = {};

    private static final Log logger = LogFactory
            .getLog(AutoConfigurationImportSelector.class);

    private ConfigurableListableBeanFactory beanFactory;

    private Environment environment;

    private ClassLoader beanClassLoader;

    private ResourceLoader resourceLoader;

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        try {
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                    .loadMetadata(this.beanClassLoader);
            AnnotationAttributes attributes = getAttributes(annotationMetadata);
            List configurations = getCandidateConfigurations(annotationMetadata,
                    attributes);
            configurations = removeDuplicates(configurations);
            configurations = sort(configurations, autoConfigurationMetadata);
            Set exclusions = getExclusions(annotationMetadata, attributes);
            checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = filter(configurations, autoConfigurationMetadata);
            fireAutoConfigurationImportEvents(configurations, exclusions);
            return configurations.toArray(new String[configurations.size()]);
        }
        catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }

    protected boolean isEnabled(AnnotationMetadata metadata) {
        return true;
    }

    
    protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
        String name = getAnnotationClass().getName();
        AnnotationAttributes attributes = AnnotationAttributes
                .fromMap(metadata.getAnnotationAttributes(name, true));
        Assert.notNull(attributes,
                "No auto-configuration attributes found. Is " + metadata.getClassName()
                        + " annotated with " + ClassUtils.getShortName(name) + "?");
        return attributes;
    }

    
    protected Class getAnnotationClass() {
        return EnableAutoConfiguration.class;
    }

    
    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;
    }

    
    protected Class getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
    }

    private void checkExcludedClasses(List configurations,
            Set exclusions) {
        List invalidExcludes = new ArrayList(exclusions.size());
        for (String exclusion : exclusions) {
            if (ClassUtils.isPresent(exclusion, getClass().getClassLoader())
                    && !configurations.contains(exclusion)) {
                invalidExcludes.add(exclusion);
            }
        }
        if (!invalidExcludes.isEmpty()) {
            handleInvalidExcludes(invalidExcludes);
        }
    }

    
    protected void handleInvalidExcludes(List invalidExcludes) {
        StringBuilder message = new StringBuilder();
        for (String exclude : invalidExcludes) {
            message.append("\t- ").append(exclude).append(String.format("%n"));
        }
        throw new IllegalStateException(String
                .format("The following classes could not be excluded because they are"
                        + " not auto-configuration classes:%n%s", message));
    }

    
    protected Set getExclusions(AnnotationMetadata metadata,
            AnnotationAttributes attributes) {
        Set excluded = new LinkedHashSet();
        excluded.addAll(asList(attributes, "exclude"));
        excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
        excluded.addAll(getExcludeAutoConfigurationsProperty());
        return excluded;
    }

    private List getExcludeAutoConfigurationsProperty() {
        if (getEnvironment() instanceof ConfigurableEnvironment) {
            RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
                    this.environment, "spring.autoconfigure.");
            Map properties = resolver.getSubProperties("exclude");
            if (properties.isEmpty()) {
                return Collections.emptyList();
            }
            List excludes = new ArrayList();
            for (Map.Entry entry : properties.entrySet()) {
                String name = entry.getKey();
                Object value = entry.getValue();
                if (name.isEmpty() || name.startsWith("[") && value != null) {
                    excludes.addAll(new HashSet(Arrays.asList(StringUtils
                            .tokenizeToStringArray(String.valueOf(value), ","))));
                }
            }
            return excludes;
        }
        RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(getEnvironment(),
                "spring.autoconfigure.");
        String[] exclude = resolver.getProperty("exclude", String[].class);
        return (Arrays.asList(exclude == null ? new String[0] : exclude));
    }

    private List sort(List configurations,
            AutoConfigurationMetadata autoConfigurationMetadata) throws IOException {
        configurations = new AutoConfigurationSorter(getMetadataReaderFactory(),
                autoConfigurationMetadata).getInPriorityOrder(configurations);
        return configurations;
    }

    private List filter(List configurations,
            AutoConfigurationMetadata autoConfigurationMetadata) {
        long startTime = System.nanoTime();
        String[] candidates = configurations.toArray(new String[configurations.size()]);
        boolean[] skip = new boolean[candidates.length];
        boolean skipped = false;
        for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
            invokeAwareMethods(filter);
            boolean[] match = filter.match(candidates, autoConfigurationMetadata);
            for (int i = 0; i < match.length; i++) {
                if (!match[i]) {
                    skip[i] = true;
                    skipped = true;
                }
            }
        }
        if (!skipped) {
            return configurations;
        }
        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);
    }

    protected List getAutoConfigurationImportFilters() {
        return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class,
                this.beanClassLoader);
    }

    private MetadataReaderFactory getMetadataReaderFactory() {
        try {
            return getBeanFactory().getBean(
                    SharedMetadataReaderFactoryContextInitializer.BEAN_NAME,
                    MetadataReaderFactory.class);
        }
        catch (NoSuchBeanDefinitionException ex) {
            return new CachingMetadataReaderFactory(this.resourceLoader);
        }
    }

    protected final  List removeDuplicates(List list) {
        return new ArrayList(new LinkedHashSet(list));
    }

    protected final List asList(AnnotationAttributes attributes, String name) {
        String[] value = attributes.getStringArray(name);
        return Arrays.asList(value == null ? new String[0] : value);
    }

    private void fireAutoConfigurationImportEvents(List configurations,
            Set exclusions) {
        List listeners = getAutoConfigurationImportListeners();
        if (!listeners.isEmpty()) {
            AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this,
                    configurations, exclusions);
            for (AutoConfigurationImportListener listener : listeners) {
                invokeAwareMethods(listener);
                listener.onAutoConfigurationImportEvent(event);
            }
        }
    }

    protected List getAutoConfigurationImportListeners() {
        return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class,
                this.beanClassLoader);
    }

    private void invokeAwareMethods(Object instance) {
        if (instance instanceof Aware) {
            if (instance instanceof BeanClassLoaderAware) {
                ((BeanClassLoaderAware) instance)
                        .setBeanClassLoader(this.beanClassLoader);
            }
            if (instance instanceof BeanFactoryAware) {
                ((BeanFactoryAware) instance).setBeanFactory(this.beanFactory);
            }
            if (instance instanceof EnvironmentAware) {
                ((EnvironmentAware) instance).setEnvironment(this.environment);
            }
            if (instance instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) instance).setResourceLoader(this.resourceLoader);
            }
        }
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory);
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }

    protected final ConfigurableListableBeanFactory getBeanFactory() {
        return this.beanFactory;
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.beanClassLoader = classLoader;
    }

    protected ClassLoader getBeanClassLoader() {
        return this.beanClassLoader;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    protected final Environment getEnvironment() {
        return this.environment;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    protected final ResourceLoader getResourceLoader() {
        return this.resourceLoader;
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE - 1;
    }

}
View Code
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    }
    try {
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                .loadMetadata(this.beanClassLoader);
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        List configurations = getCandidateConfigurations(annotationMetadata,
                attributes);
        configurations = removeDuplicates(configurations);
        configurations = sort(configurations, autoConfigurationMetadata);
        Set exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = filter(configurations, autoConfigurationMetadata);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return configurations.toArray(new String[configurations.size()]);
    }
    catch (IOException ex) {
        throw new IllegalStateException(ex);
    }
}

SpringBoot 1.x 之入门_第2张图片

  • 从上面的截图中,我们可以看到会给容器中注册非常多的自动配置类(xxxAutoConfiguration),换言之,就是给容器中导入这个场景所需要的所有组件,并配置好这些组件,有了自动配置了,就免去了我们手动编写配置注入功能组件等工作。
  • 其中,查看下面的代码:
List configurations = getCandidateConfigurations(annotationMetadata,
                attributes);
    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;
    }
    protected Class getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
    }
    public static List loadFactoryNames(Class factoryClass, ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        try {
            Enumeration urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
            List result = new ArrayList();
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                String factoryClassNames = properties.getProperty(factoryClassName);
                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }
            return result;
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
                    "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
    }
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
  • 我们可以知道,将会加载类路径下的META-INF/spring.factories文件中获取EnableAutoConfiguration指定的值,并将这些值作为自动配置类导入到容器中,自动配置类就生效,帮助我们自动配置工作。

SpringBoot 1.x 之入门_第3张图片

 

  • 总而言之,J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-1.5.9.RELEASE.jar中。

你可能感兴趣的:(SpringBoot 1.x 之入门)