栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot解析

一.快速搭建SpringBoot应用

1. 创建一个maven项目。pom.xml文件中添加如下的内容。

spring-boot-starter-parent 才能继承父项目中所有的依赖。  
其父项目为spring-boot-starter-dependencies, 定义好了组件版本、组件坐标、插件管理。
帮我们管理了springboot中的所有依赖版本,解决了版本冲突的问题。叫做版本仲裁中心

spring-boot-starter-xxx. 以spring-boot-starter-web为例,其中定义好了web开发时所需的大部分依赖。  帮我们整合了第三方库,做了默认配置。需要修改的话到application.properties中修改

plugin: 生成的jar包能都用java -jar独立运行

spring-boot-configuration-processor: 在编写配置文件的时候有自动提示。 IDEA的Annotation Processors 要勾选Enable annotation procession

    
        org.springframework.boot
        spring-boot-starter-parent
        2.3.3.RELEASE
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
       
       
            org.springframework.boot
            spring-boot-configuration-processor
            true
        

        
            org.springframework.boot
            spring-boot-devtools
            true
        

    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                2.3.3.RELEASE
            
        
    

 2. 编写controller,标记RequestMapping() 指定映射路径

3. SpringBoot启动入口, 使用@SpringBootAppication注解标记。在类中运行springApplication.run()

4. 在Resoures文件夹下加上配置文件 application.properties, 可以配置一些项目属性,比如端口等

5. 创建springBoot父项目。创建好一个maven项目,在该maven项目中创建modules。要在父项目的pom中加上pom

二. 自动配置原理解析   登录 | ProcessOn

查看启动类上的注解@SpringBootApplication

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
@Target({ElementType.TYPE})   
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@SpringBootConfiguration   *****等同与@Configuration,既标注该类是Spring的一个配置类 
@EnableAutoConfiguration   *****SpringBoot自动配置功能开启
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {...}

按住Ctrl点击查看注解@EnableAutoConfiguration。 告诉SpringBoot去开启自动配置类,会自动加载自动配置类,{AutoConfigurationimportSelector}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@AutoConfigurationPackage   \将当前所在包路径存到basePackage中供内部使用
@import({AutoConfigurationimportSelector.class}) 
\导入了AutoConfigurationimportSelector类
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class[] exclude() default {};

    String[] excludeName() default {};
}


AutoConfigurationimportSelector 去meta-INF/spring.factories中加载类
其中,SpringFactoriesLoader.loadFactoryNames 方法的作用就是从
meta-INF/spring.factories文件中读取指定类对应的类名称列表。
文件存在大量的以AutoConfiguration为结尾的类名称,
这些类就是存有自动配置信息的类,
而SpringApplication在获取这些类名后再加载


例如:ActiveMQAutoConfiguration
@Configuration(
    proxyBeanMethods = false
)
@AutoConfigureBefore({JmsAutoConfiguration.class})
@AutoConfigureAfter({JndiConnectionFactoryAutoConfiguration.class})
@ConditionalOnClass({ConnectionFactory.class, ActiveMQConnectionFactory.class})
@ConditionalOnMissingBean({ConnectionFactory.class})

@EnableConfigurationProperties({ActiveMQProperties.class, JmsProperties.class}) 
*******该注解很重要。springBoot会将类ActiveMQProperties【ActiveMQ的属性类】
中的属性和前缀为spring.activemq配置文件中的默认值一一对应【映射】起来

@import({ActiveMQXAConnectionFactoryConfiguration.class, ActiveMQConnectionFactoryConfiguration.class})
public class ActiveMQAutoConfiguration {
    public ActiveMQAutoConfiguration() {
    }
}

用@import()导入了AutoConfigurationimportSelector. 
该类继承了DeferredimportimportSelector类。
会调用getimportGroup()返回的类,如果返回类实现了Group接口,
会调用Group类的Selectimportorf方法。

拿其中一个举例子HttpEncodingAutoConfiguration

@Configuration(
    proxyBeanMethods = false
)

@EnableConfigurationProperties({ServerProperties.class})   
\每个自动配置都有一个自动配置xxxProperties属性类

\还有Condition注解,满足条件才会将自动配置类注入到IoC容器中
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
    prefix = "server.servlet.encoding",
    value = {"enabled"},
    matchIfMissing = true
)

public class HttpEncodingAutoConfiguration {}

依赖中有autoconfiguration包。作用????????

三. SpringBoot概览

SpringBoot是Spring的一站式解决方案,主要用来简化Spring使用,提供了各种启动器,简化了配置,容易上手。

优点:

1. 快速 构建 一个独立的 Spring 应用程序 ; 2. 嵌入的 Tomcat 、 Jetty 或者 Undertow,无须部署 WAR 文件; 3. 提供starter POMs来简化Maven配置和减少版本冲突所带来的问题; 4. 对Spring和第三方库提供默认配置,也可修改默认值,简化框架配置; 5. 提供生产就绪型功能,如指标、健康检查和外部配置; 6. 无需配置XML,无代码生成,开箱即用; 四. SpringBoot配置文件

SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties或者application.yml(application.yaml)进行配置。

SpringBoot默认会从Resources目录下加载application.properties或application.yml(application.yaml)文件。

application.properties文件是键值对类型的文件,YML文件是以数据为核心的,比传统的xml方式更加简洁。

SpringBoot的配置文件,主要的目的就是对默认配置信息进行修改的,但在配置时的key从哪里去查询呢?我们可以查阅SpringBoot的官方文档

文档URL:

https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/reference/htmlsingle/#common-application-properties

配置文件与属性值映射: 将配置文件的值注入到Bean对应的属性中

1.可以通过@Value注解将配置文件中的值映射到一个Spring管理的Bean的字段上,不需要字段提供setter.

2.@ConfigurationProperties(prefix="配置文件中的key的前缀")可以将配置文件中的配置自动与实体进行映射。但需要字段必须提供set方法。

@Value获取值和@ConfigurationProperties获取值比较 3.  @PropertySource :加载指定的配置文件; 4. @importResource :导入Spring的配置文件,让配置文件里面的内容生效; Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别; 想让Spring的配置文件生效,加载进来;@importResource标注在一个配置类上

配置文件的读取顺序

在spring-boot-starter-parent的pom文件中,


  **/application*.yml
  **/application*.yaml
  **/application*.properties

所以,配置文件的读取顺序为上述。同时读取,配置文件之间为互补关系。

配置文件一般是在resources根目录下。优先级由低到高如下:

1. classpath根目录下的 2. classpath根config/ 3. 项目根目录: 如果当前项目是继承/耦合 关系maven项目的话,项目根目录=父maven项目的根目录 4. 项目根目录/config 5. 命令行启动指定的直接子目录 /config Profile文件 不同的环境需要不同的配置环境;同一个位置下profile优先级较高

application.properties     **** spring.profiles.active=prod  指定当前配置文件为生产环境的配置文件

application-dev.properties  ***开发的配置文件

application-prod.properties  ***生产环境的配置文件

五. 一些面试题

1. SpringBoot中devtools热部署

1.1 添加依赖

       
            org.springframework.boot
            spring-boot-devtools
            true
        

1.2修改IDEA配置

(1)File-Settings-Compiler-Build Project automatically (2)ctrl + shift + alt + / ,选择Registry,勾上 Compiler autoMake allow when app running

六. 常见注解

七. SpringBoot启动原理 1 调用SpringApplication.run启动springboot应用   SpringApplication.run(Application.class, args); 2. 创建SpringApplication, 通过 SpringFactoriesLoader.loadFactoryNames(type, classLoader) 加载spring-factories文件中特定的类 (new SpringApplication(primarySources)).run(args); 3.运行run方法 (new SpringApplication(primarySources)). run(args);
 
public ConfigurableApplicationContext run(String... args) {
        *****springBoot启动耗时******
        StopWatch stopWatch = new StopWatch();
        stopWatch.start(); 
         
        ConfigurableApplicationContext context = null;
        Collection exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        
        *******去spring.factroies中读取了SpringApplicationRunListener 的组件, 就是用来发布事件或者运行监听器*****
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        *****发布1.ApplicationStartingEvent事件,在运行开始时发送*****
        listeners.starting();

        Collection exceptionReporters;
        try {
            *****根据命令行参数 实例化一个ApplicationArguments*****
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

            *****预初始化环境: 读取环境变量,读取配置文件信息(基于监听器)*
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            *****创建SpringApplicationContext*****
            context = this.createApplicationContext();
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);

            ****预初始化spring上下文**
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

            *****加载spring ioc 容器 【相当重要】 由于是使用AnnotationConfigServletWebServerApplicationContext 启动的spring容器所以springboot对它做了扩展: 加载自动配置类:invokeBeanFactoryPostProcessors , 创建servlet容器onRefresh
            this.refreshContext(context);

            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }
 

--->this.refresh(context)

---> AbstractApplicationContext.invokeBeanFactoryPostProcessors(beanFactory);

--->PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

--->invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

--->PostProcessorRegistrationDelegate.postProcessor.postProcessBeanDefinitionRegistry(registry);  postProcessor就包含 ConfigurationClassPostProcessor ,implenment

--->ConfigurationClassPostProcessor 。processConfigBeanDefinitions(registry);  //处理各种配置类,没有@Configuration立即返回。解析@Configuration注解。通常是我们的主配置类

--->。。。--->ConfigurationClassParser.doProcessConfigurationClass() 解析各类注解  @PropertySource   @ComponentScan    @import   @importResource  @Bean

---> ConfigurationClassParser.processimports() 在解析import注解时,就得到AutoConfigurationimportSelector名称,然后实例化成selector  Bean   

if (selector instanceof DeferredimportSelector) { //如果是
   this.deferredimportSelectorHandler.handle(configClass, (DeferredimportSelector) selector);
}
else {
   String[] importClassNames = selector.selectimports(currentSourceClass.getmetadata());
   Collection importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
   processimports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}

ConfigurationClassPostProcessor  BeanDefinitionRegistryPostProcessor——动态注册Bean到Spring容器_跨语言,跨平台,跨应用-CSDN博客

加载spring-factories文件 SpringFactoriesLoader.loadFactoryNames(type, classLoader)

1. 初始化SpringApplication 从spring.factories 读取 listener ApplicationContextInitializer 。 2.运行run方法 3.读取 环境变量 配置信息..... 4. 创建springApplication上下文: ServletWebServerApplicationContext 5. 预初始化上下文 : 读取启动类 6.调用refresh 加载ioc容器 加载所有的自动配置类 创建servlet容器 7.在这个过程中springboot会调用很多监听器对外进行

今日头条

-------------------------------2021.7.10-----------------------

掌握自动配置原理和启动流程,就掌握了SpringBoot.

1.springBoot集成其他框架,一般使用@Enablexxx引入@import(类)注解,引入一个类,这个类是实现功能的主要逻辑。

2.import大致有3种用法:

@import(类); 

@import(importSelector接口的实现类);

@import(importBeanDefinitionRegistrar接口实现类)

interface DeferredimportSelector extends importSelector  在其他注解解析之后最后解析,例如:SpringBoot默认配置SqlSessionFactory,用户想重新定制一个特定功能的SqlSessionFactory, 就得先加载,默认的通过@Condition注解就不注入到容器中了。从而实现了条件配置。

在application.properties中添加debug=true,能够看到加载了哪些自动配置类。

启动:

ContextLoaderListener启动了SpringApplicationContext

问题1:SpringBoot的jar为什么直接可以运行?

在POM.xml文件中添加了spring-boot-maven-plugin插件,生成的jar就可以直接运行。插件的作用是生成MANIFEST.MF(文件中指定了start-class, );把依赖的jar

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/460041.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号