SpringBoot:SpringBoot原理

SpringBoot高级

SpringBoot配置

配置文件优先级

按照yaml>yml>properties的顺序加载

存在相同配置项,后加载的会覆盖先加载的

加载顺序越靠后,优先级越高

SpringBoot存在其他的多种方式进行配置,如下所示,越靠下优先级越高

1. Default properties (specified by setting SpringApplication.setDefaultProperties).
2. @PropertySource annotations on your @Configuration classes. Please note that such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins.
3. Config data (such as application.properties files). (上述配置文件的方式)
4. A RandomValuePropertySource that has properties only in random.*.
5. OS environment variables. (系统环境变量方式)
6. Java System properties (System.getProperties()). (java系统参数方式)
7. JNDI attributes from java:comp/env.
8. ServletContext init parameters.
9. ServletConfig init parameters.
10. Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).
11. Command line arguments. (命令行参数方式)
12. properties attribute on your tests. Available on @SpringBootTest and the test annotations for testing a particular slice of your application.
13. @DynamicPropertySource annotations in your tests.
14. @TestPropertySource annotations on your tests.
15. Devtools global settings properties in the $HOME/.config/spring-boot directory when devtools is active.
系统环境变量方式配置

系统环境变量:将一些配置在系统中设置成全局的环境变量

在run configurations中进行配置
请添加图片描述

配置规则

配置项目的

.

使用

_

替换

删除所有的

-

字母全部转为大写

java系统参数方式

(System.getProperties())

在run configurations中进行配置

请添加图片描述

指在运行时,通过

-Dkey=value

进行参数指定

eg:java -Dserver.port=8085 -jar xxxx.jar(命令行)-DServer.port=8085(idea中)
命令行参数方式

在run configurations中进行配置

请添加图片描述

在运行命令后面通过

--key=value
eg:java -jar xxxx.jar --server.port=8086

Spring Bean管理

手动获取容器中的bean对象

在Spring容器中提供了可以主动从IOC容器中获取bean对象的方法,通过

@Resourse
private ApplicationContext applicationContext

对象进行获取

指定类型获取bean
Bean bean = this.applicationContext.getBean(Bean.class);
通过bean的名称获取bean,返回Object类型对象

对象名默认为首字母小写

Object bean = this.applicationContext.getBean("bean");
通过bean的名称获取bean,指定返回对象的类型
Bean bean = this.applicationContext.getBean("bean",Bean.class);

Bean的作用域

在Spring中支持五种作用域,但后三种只在web环境生效

singleton
//容器内同名称的bean只有一个实例(单例)(默认)
//在容器启动时被创建,可以使用@Lazy注解来延迟初始化(延迟到第一次使用时)
prototype
//每次使用该bean时会创建新的实例(非单例)
request
//每个请求范围内会创建新的实例(web环境中)
session
//每个会话范围内会创建新的实例(web环境中)
application
//每个应用范围内会创建新的实例(web环境中)

通过Spring中的

@Scope(ConfigurableBeanFactory.SCOPE_作用域)

注解进行配置,属性为enum类型

需要在标注了

@Configuration

注解的spring配置类上进行配置

第三方Bean

不是我们自己编写的,由第三方依赖提供的类,对于这种类我们无法做到直接通过@Component进行注册

就需要用到

@Bean

注解

通过在配置类中构造一个方法返回一个需要的对象提交到Spring容器中,就可以在需要时进行注入

@Scope(...)
@Configuration()
class Config{
	@Bean //将方法的返回值提交到IOC容器
    //可以通过bean注解的name或者value属性声明bean的名称(默认为方法名)
    //如果第三方bean需要依赖其他的对象,直接在bean注解的方法中设置形参即可,会进行自动注入
    Obj objf(){
		return new Obj();
	}
}

就可以在需要时进行注入

map集合转JSON
Map<String,Object>data = new HashMap<>();
//JSON转化对象
ObjectMapper objectMapper = new ObjectMapper();
//序列化Map为JSON字符串
String json = objectMapper.writeValueAsString(对象名);

SpringBoot原理

SpringBoot框架是Spring4.0之后对Spring框架的简化,提供了两个非常重要的功能:起步依赖和自动配置

起步依赖原理

起步依赖可以大幅简化pom文件中的依赖配置,解决了Spring框架中依赖配置繁琐的问题

引入起步依赖直接包含了一系列web开发需要的依赖

spring-webmvc依赖
//Spring框架进行web程序开发所需要的依赖
servlet-api依赖
//Servlet基础依赖
jackson-databind依赖
//JSON处理工具包
还有AOP依赖,aspect依赖等等
起步依赖
springboot-starter-web

通过maven传递的方式将常见的其他依赖都自动传递进来

自动配置原理

自动配置可以大幅简化使用时bean的声明和bean的配置

自动配置就是当Spring容器启动后,一些配置类,bean对象就自动存入了IOC容器中,无需手动声明,从而简化开发.

@Configuration底层就是@Component,所以配置类也是Spring容器中的一个bean对象

在IOC容器中有很多配置类,都是在SpringBoot启动时加载进来的,同时也会生成很多的bean对象.

加载jar中的bean到IOC容器

当我们通过坐标引入第三方依赖后,尝试使用前面说过的applicationContext对象获取被@Component标注的对象

会发现出现异常找不到对应对象

原因是因为没有Spring组件扫描到

可以通过以下两个方法解决

增加@ComponentScan组件扫描

在启动类上增加@ComponentScan注解同时在参数中指定需要扫描的包

@ComponentScan({"com.test","com.example"})

使用繁琐而且性能也低

使用@Import导入

在启动类上导入

导入方式有以下几种

使用@Import导入普通类

被导入的类会被Spring加载到IOC容器中

@Import(Bean.class)
使用@Import导入配置类

在需要引入的jar包中编写配置类,在配置类中完成对象的注册

可以在配置类中注册多个对象

在引入类的启动类上对jar包中配置类进行引入

@Import(com.example.Config.TokenConfig.class)
public class MyApplication {}


@Configuration
public class TokenConfig {
    @Bean
    public TokenParser tokenParser(){
        return new TokenParser();
    }
}
使用@Import导入ImportSelector接口实现类

通过接口中的selectImports方法返回一个String类型数组,包含要引入的类

@Import(ImportSelectorImpl.class)

public class MyImportSelector implements ImportSelector {

    //把返回数组中的每一个bean注册到IOC容器中
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        return new String[]{"com.example.HeaderConfig","com.example.TokenParser"};
    }
}
指定第三方依赖的bean对象和配置类

使用第三方依赖提供的注解,一般以Enable开头,注解中封装了一个@Import注解

@SpringBootApplication
@EnableHeaderConfig  //使用第三方依赖提供的Enable开头的注解
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

//第三方写的注解内容
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)//指定要导入哪些bean对象或配置类
//引入接口实现类对象
public @interface EnableHeaderConfig {
}

源码跟踪

@SpringBootApplication注解中包含了
@SpringBootConfiguration
//使用了@Configuration表明SpringBoot启动类就是一个配置类
//包含@Indexed注解用来加速应用启动
@EnableAutoConfiguration
//自动配置的核心注解
//自动载入基于META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件、META-INF/spring.factories文件中配置类的集合
//这两个配置文件在autoconfigure包中
@ComponentScan
//用来进行组件扫描,扫描引导类所在的包及其子包下所有带有Spring注解的类
//启动类因为具有此注解所以具备扫描包功能
//属性中可以设置不进行扫描

请添加图片描述

@Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({Jackson2ObjectMapperBuilder.class})
    static class JacksonObjectMapperConfiguration {
        JacksonObjectMapperConfiguration() {
        }

        @Bean
        @Primary
        @ConditionalOnMissingBean
        ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
            return builder.createXmlMapper(false).build();
        }
    }

Conditional

以Conditional开头的注解,一般都是条件装配的注解

@Conditional

按照一定的条件进行判断,在满足给定的条件后会注册对应bean对象到Spring的IOC容器中

派生了大量的子注解

@ConditionalOnClass:

判断环境中有对应类的字节码文件,注册bean到IOC容器

@ConditionalOnClass(name="类名")
@ConditionalOnMissBean:
@ConditionalOnMissBean(name="bean名称")
//环境中没有对应的名称的bean,注册bean到IOC容器
@ConditionalOnMissBean(xxx.class)
//环境中没有对应类型的bean
@ConditionalOnMissBean
//环境中没有当前类型的bean
@ConditionalOnProperty:

判断配置文件中有对应的属性,注册bean到IOC容器中

@ConditionalOnProperty(name="键",havingValue="值")
@Bean
    @ConditionalOnClass(name="io.jsonwebtoken.Jwts")//环境中存在指定的这个类,才会将该bean加入IOC容器
    public HeaderParser headerParser(){
        return new HeaderParser();
    }

自动配置总结

自动配置的原理其实就是在程序启动时,加载上述的两个配置文件中定义的配置类,将这些类的全限定名封装到String类型的数组中.

再通过@Import注解将这些配置类全部加载到Spring的IOC容器中,配置类中的bean会根据@Conditional的条件进行选择性的装配.

在配置文件的配置类中定义了@Bean标识的方法,Spring会自动调用配置类中的这些方法并将返回值注册到IOC容器中.

自定义starter

SpringBoot中的起步依赖,当我们需要在实际项目开发中使用通用的第三方依赖,就需要用到自定义起步依赖.

SpringBoot官方starter命名:
spring-boot-starter-xxxx
第三方组织提供的starter命名:
xxxx-spring-boot-starter

在自定义一个起步依赖starter的时候,需要按规范定义两个模块

autoconfigure模块(自动配置)

引入时只需要引入一个起步依赖即可,autoconfigure自动配置的依赖会被传递下来

在autoconfigure模块中创建自动配置类

在配置类中,创建一个@Bean方法在spring加载时被自动读取

package com.aliyun.oss;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration//当前类为Spring配置类
@EnableConfigurationProperties(AliOSSProperties.class)//导入AliOSSProperties类,并交给SpringIOC管理
public class AliOSSAutoConfiguration {

    //创建AliOSSUtils对象,并交给SpringIOC容器
    @Bean
    @ConditionalOnMissingBean
    public AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties){
        AliOSSUtils aliOSSUtils = new AliOSSUtils();
        aliOSSUtils.setAliOSSProperties(aliOSSProperties);
        return aliOSSUtils;
    }

}

将配置类的全限定名写入配置文件.imports

com.aliyun.oss.AliOSSAutoConfiguration
starter模块(进行依赖管理[把程序开发所需的依赖定义在starter起步模块中])

在starter模块中,我们只需要在pom文件中引入autoconfigure,就可以通过依赖传递只引入starter模块实现对整个jar包的依赖引入

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/618595.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vm虚拟机安装网络适配器驱动卡死/无响应/无限等待状态

大部分原因都是以前的vm没有卸载干净所导致的&#xff0c;只需要使用CCleaner清楚干净就好 使用控制面板里的卸载把VM卸载干净 使用CCleaner软件删除干净注册表&#xff0c;这个软件百度很容易找到&#xff0c;只有十兆左右 打开下载好的软件&#xff0c;不需要注册码&#xff…

长安汽车:基于云器 Lakehouse 的车联网大数据平台建设

近年来随着智能汽车行业的迅速发展&#xff0c;数据也在呈爆炸式增长。长安大数据平台承接了长安在生产上大部分流量应用及日常生产业务应用。本文将分享长安汽车在车联网场景下大数据平台建设面临的一些挑战和具体落地的实践。 主要内容如下&#xff1a; 1. 背景介绍 2. 长…

Java数组:三种初始化

一.静态初始化 代码演示&#xff1a; //静态初始化:创建 赋值int[] a {1,2,3,4,5,6};System.out.println(a[0]); 二.动态初始化 代码演示&#xff1a; //动态初始化:包含默认初始化int[] b new int[10];b[0] 10;System.out.println(b[0]); //10System.out.println(b[1])…

25计算机考研院校数据分析 | 中南大学

中南大学&#xff08;Central South University&#xff09;&#xff0c;位于湖南省长沙市&#xff0c;是中华人民共和国教育部直属的全国重点大学 &#xff0c;中央直管副部级建制&#xff0c;位列国家“双一流”、“985工程”、“211工程”&#xff0c;入选国家“2011计划”牵…

MySQL前缀索引、脏页和干净页、COUNT(*)讨论、表删除内存问题

文章目录 如何加索引如何给身份证号添加索引 SQL语句变慢脏页 (Dirty Pages)干净页 (Clean Pages)为何区分脏页和干净页处理脏页管理策略 flush如何控制 为什么删除表数据后表文件大小不变问题背景核心原因数据存储方式参数影响 解决方案1. 调整innodb_file_per_table设置2. 使…

vs2019 cpp20 规范的线程头文件 <thread> 注释并探讨两个问题

&#xff08;1&#xff09;学习线程&#xff0c;与学习其它容器一样&#xff0c;要多读 STL 库的源码。很多知识就显然而然的明白了。也不用死记硬背一些结论。上面上传了一份注释了一下的 源码。主要是补充泛型推导与函数调用链。基于注释后的源码探讨几个知识点。 STL 库的多…

【SpringBoot】 什么是springboot(三)?springboot使用ajax、springboot使用reids

文章目录 SpringBoot第五章第六章1、springboot使用ajax2、springboot使用reids1、单机版**使用步骤**1-5步67-9步RedisTemplate使用RedisTemplate2、集群版开启集群项目配置1234-5第七章1、springboot文件上传使用步骤1-234-52、springboot邮件发送步骤1-23453、springboot拦截…

【智能算法】最优捕食算法(OFA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2017年&#xff0c;GY Zhu受到动物行为生态学理论启发&#xff0c;提出了最优捕食算法&#xff08;Optimal Foraging Algorithm, OFA&#xff09;。 2.算法原理 2.1算法思想 OFA灵感来源…

网络编程学习笔记1

文章目录 一、socket1、创建socket2、网络通信流程3、accept()函数4、signal()函数5、recv()函数6、connect()函数 二、I/O多路复用1.select模型2.poll模型3.epoll模型 注 一、socket 1、创建socket int socket(int domain,int type,int protocol); //返回值&#xff1a;一个…

微信小程序的Vant Weapp组件库(WeUI组件库)

一、定义&#xff1a; 是一套开源的微信小程序UI组件库。提供了一整套UI基础组件和业务组件&#xff0c;能够快速地搭配出一套风格统一的页面 二、使用&#xff1a; &#xff08;1&#xff09;&#xff08;找到.eslintrc.js 右键&#xff0c;在内件终端打开&#xff09;打开命…

|Python新手小白中级教程|第二十八章:面向对象编程(类定义语法私有属性类的继承与多态)(4)

文章目录 前言一、类定义语法二、私有方法和私有属性1.私有属性2.私有方法 三、类“继承”1.初识继承2.使用super函数调用父类中构造的东西 四、类“多态”1.多态基础2.子类不同形态3.使用isinstance函数与多态结合判断类型 总结 前言 大家好&#xff0c;我是BoBo仔吖&#xf…

RocketMQ学习笔记(一)

一、基本概念 生产者&#xff08;Producer&#xff09;&#xff1a;也称为消息发布者&#xff0c;是RocketMQ中用来构建并传输消息到服务端的运行实体&#xff0c;举例&#xff1a;发信者主题&#xff08;Topic&#xff09;&#xff1a;Topic是RocketMQ中消息传输和存储的顶层…

【全开源】Java知识付费教育付费资源付费平台公众号小程序源码

特色功能&#xff1a; 多样化的内容呈现&#xff1a;资源付费平台小程序支持图文、音视频、直播等多种形式的内容呈现&#xff0c;为用户提供了丰富的学习体验。直播课程&#xff1a;专家或讲师可以通过小程序进行在线授课&#xff0c;与用户实时互动&#xff0c;增强了学习的…

再有人说数字孪生大屏没有用,用这8条怼回去。

数字孪生大屏之所以受到欢迎&#xff0c;主要有以下几个原因&#xff1a; 实时数据可视化 数字孪生大屏可以将实时数据以直观的可视化形式展示出来&#xff0c;让用户能够一目了然地了解数据的状态和趋势。这样可以帮助用户更好地理解和分析数据&#xff0c;及时做出决策和调…

动态规划算法练习——计数问题

题目描述 给定两个整数 a 和 b&#xff0c;求 a 和 b 之间的所有数字中 0∼9 的出现次数。 例如&#xff0c;a1024&#xff0c;b1032&#xff0c;则 a 和 b 之间共有 9 个数如下&#xff1a; 1024 1025 1026 1027 1028 1029 1030 1031 1032 其中 0 出现 10 次&#xff0c;1 出现…

蓝桥杯-网络安全比赛(7)基础知识 HTTP、TTL、IP数据包、MSS、MTU、ARP、LLMNR、MDNS、NBNS。

1. IP中TTL值能够给我提供什么信息&#xff1f;2. IP头部中标志、13位偏移、32位源IP地址、目标IP、IP数据包格式&#xff0c;有多少字节3. IP头部中的16位标识是什么&#xff1f;4. MSS 和MTU分别有多大&#xff1f;5. 怎么获取路由IP信息&#xff1f;PING、NSLOOKUP、TRACERT…

day6Qt作业

人脸识别系统 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <opencv2/opencv.hpp> #include <iostream> #include <math.h> #include<opencv2/face.hpp> #include <vector> #include <map> #include <QMessag…

创建一个react项目(router,store,axios,antd)最后有项目地址

第一步&#xff1a;使用cra脚手架 创建项目 文档地址&#xff1a;Create React App 中文文档 npx create-react-app 你的项目名称 第二步&#xff1a;整理项目结构和删除多余代码 目标效果图&#xff1a; 在src目录下分别新建apis,assets,components,pages,router,store,ut…

重学JavaScript核心知识点(二)—— 详解Js中的模块化

详解Js中的模块化 1. 模块化的背景2. 来看一个例子3. 优雅的做法 —— 创建模块对象4. 模块与类&#xff08;class&#xff09;5. 合并模块6. 动态加载模块 1. 模块化的背景 JavaScript 在诞生之初是体积很小的&#xff0c;早期&#xff0c;它们大多被用来执行独立的脚本任务&…

C++初学者,使用命令行编绎C文件

今天在家里&#xff0c;闲来无事。又开始学习制作Helloworld! VStudio 版本众多&#xff0c;用哪个好呢&#xff0c;真是不好选择。今天就使用网上的大神&#xff1a;theoractice&#xff0c;制造的版本来学习C&#xff0c;我喜欢2013这个版本&#xff0c;真是太好用了。不但C…