这里写自定义目录标题

  • Springboot的核心功能是什么
  • Springboot注解
  • 自动配置的原理
  • 其他的一些注解
  • Springboot的运行流程
  • 1、mian方法
  • 2、执行run方法
  • Springboot配置文件的加载顺序


Springboot的核心功能是什么

1、运行独立的spring 项目
Spring Boot 可以以 jar 包的形式独立运行,运行一个 Spring Boot 项目只需通过 java–jar xx.jar 来运行。
2、内嵌的servet容器
可选择内嵌的tomcat,无需打包成war部署项目
3、提供starter简化maven配置
springboot提供了starter pom从而简化了maven的配置
4、自动配置spring

Springboot注解

一、首先我们先看springboot的运行代码

@SpringBootApplication
public class NotesApplication {

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

}

其中@SpringBootApplication是springboot中的核心注解,它包括了三个注解:

  • @Configuration
  • @EnableAutoConfiguration
  • @ComponentScan

相当于:@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan。

1、Configuration:

@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 {
........
}

Configuration这个注解是定义配置类的,可以替换spring中的xml配置文件
xml的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
       default-lazy-init="true">
    <!--bean定义-->
</beans>

基于Configuration注解的配置:

@Configuration
2 public class MockConfiguration{
3     //bean定义
4 }

2、@ComponentScan
对应xml中的配置元素,它自动扫描加载符合条件的组件或者bean,最终将这些bean定义加载到当前使用的容器中,非必须的。
3、@EnableAutoConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
.......
}

它帮助springboot把所以符合条件的@Configuration配置类都加载到当前SpringBoot创建并使用的IoC容器中
SpringFactoriesLoader:

public final class SpringFactoriesLoader {
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
    private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap();

    private SpringFactoriesLoader() {
    }

    public static <T> List<T> loadFactories(Class<T> factoryType, @Nullable ClassLoader classLoader) {
    ......
    }

    public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
       .......
    }
}

SpringFactoriesLoader主要功能就是从指定的配置文件META-INF/spring.factories中加载配置

自动配置的原理

Spring Boot启动的时候会通过@EnableAutoConfiguration注解(SpringFactoriesLoader)找到META-INF/spring.factories配置文件中的所有自动配置类,并对其进行加载

其他的一些注解

二、其他的一些注解:
1、@Autowired:注入依赖bean,按name注入。
2、@RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。
3、@Bean:用@Bean标注方法等价于XML中配置的bean。
4、@Value:注入Spring boot application.properties配置的属性的值
5、@Resource(name=”name”,type=”type”):没有括号内内容的话,默认byName
6、@RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。

Springboot的运行流程

springboot启动后的大致流程:springboot启动后,run方法完成了springboot的启动流程:准备Environment ----->发布事件------>创建上下文,bean ------>刷新上下文------->结束,中间穿插了一系列的监听器的动作。
接下来我们看一看源码相关的东西

1、mian方法

@SpringBootApplication
public class NotesApplication {

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

}

mian方法做了两件事:1)new 了一个SpringApplication 2)调用run方法,加载接口实例

2、执行run方法

初始化springboot后,执行run方法

public ConfigurableApplicationContext run(String... args) {
        //计时器,统计任务的执行时间
        StopWatch stopWatch = new StopWatch();
        //开始执行
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        FailureAnalyzers analyzers = null;
        this.configureHeadlessProperty();
        // 获取SpringApplicationRunListeners启动事件监听器,这里只有一个EventPublishingRunListener
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        // 封装成SpringApplicationEvent事件然后广播出去给SpringApplication中的listeners所监听
        listeners.starting();

        try {
            // 构造一个应用程序参数持有类
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 准备并配置环境
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
             // 打印banner图形
            Banner printedBanner = this.printBanner(environment);
            // 创建Spring容器
            context = this.createApplicationContext();
            new FailureAnalyzers(context);
            // 配置Spring容器
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            // 容器上下文刷新
            this.refreshContext(context);
            // 容器创建完成之后调用afterRefresh方法
            this.afterRefresh(context, applicationArguments);
            // 调用监听器,广播Spring启动结束的事件
            listeners.finished(context, (Throwable)null);
            // 停止计时器
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
            throw new IllegalStateException(var9);
        }
    }

1)获取启动监听器,启动时间监听器

private SpringApplicationRunListeners getRunListeners(String[] args) {
        Class<?>[] types = new Class[]{SpringApplication.class, String[].class};
        return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
    }

2)配置并且准备环境
判断环境,如果是web程序,创建StandardServletEnvironment;否则,创建StandardEnvironment

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
        ConfigurableEnvironment environment = this.getOrCreateEnvironment();
        this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
        ConfigurationPropertySources.attach((Environment)environment);
        listeners.environmentPrepared((ConfigurableEnvironment)environment);
        this.bindToSpringApplication((ConfigurableEnvironment)environment);
        if (!this.isCustomEnvironment) {
            environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
        }

        ConfigurationPropertySources.attach((Environment)environment);
        return (ConfigurableEnvironment)environment;
    }

3)创建spring上下文

protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch(this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
                    break;
                case REACTIVE:
                    contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
                    break;
                default:
                    contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
                }
            } catch (ClassNotFoundException var3) {
                throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
            }
        }

        return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
    }

配置spring上下文

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
        context.setEnvironment(environment);
        this.postProcessApplicationContext(context);
        this.applyInitializers(context);
        listeners.contextPrepared(context);
        if (this.logStartupInfo) {
            this.logStartupInfo(context.getParent() == null);
            this.logStartupProfileInfo(context);
        }

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

        Set<Object> sources = this.getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        this.load(context, sources.toArray(new Object[0]));
        listeners.contextLoaded(context);
    }

4)spring文件创建后返回回调方法
postProcessApplicationContext

protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
        if (this.beanNameGenerator != null) {
            context.getBeanFactory().registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", this.beanNameGenerator);
        }

        if (this.resourceLoader != null) {
            if (context instanceof GenericApplicationContext) {
                ((GenericApplicationContext)context).setResourceLoader(this.resourceLoader);
            }

            if (context instanceof DefaultResourceLoader) {
                ((DefaultResourceLoader)context).setClassLoader(this.resourceLoader.getClassLoader());
            }
        }

        if (this.addConversionService) {
            context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());
        }

    }

5)spring容器创建完成后回调afterRefresh

Springboot配置文件的加载顺序

1)properties文件;

2)YAML文件;

3)系统环境变量;

4)命令行参数;