目录
简单类型、对象类型、对象集合、数组类型、map等分别用yml和properties两种写法赋值
自动配置原理
@SpringBootApplication
作用:启动类上加的注解 ,这个类的同级别或者子包下面的组件才会被扫描到,是一个复合注解,等价于@Configuration(标明类为配置类),
@EnableAutoConfiguration(启动自动配置功能),
@ComponentScan(扫描注解)三个注解
描述注解
@Target
作用:用于修饰注解,该注解可以声明在哪些目标元素之前,也可以理解为注释类型的程序元素的种类
@Retention
作用:说明注解的生命周期以及作用域,有些注解是可以改变你代码运行结果的,有些注解不能(例如:@Override)
RetentionPolicy.SOURCE:只是在代码中有,编译后的class文件没有,所以不会造成任何影响(元注解)
RetentionPolicy.RUNTIME:对代码有影响(运行时注解)
@Documented:注解标注文档
@SpringBootConfiSguration:表示springboot启动类是一个配置类
@EnableAutoConfiguration:自动配置开关
@Import(AutoConfigurationImportSelector.class):自动导入SpringBoot自动配置类{
127个(最基本的SpringBoot的web项目+自己引入的jar)自动配置类(一个自动配置类等于一个application.xml文件,也就是说一个自动配置类中可能有多个bean),根据我们的需要保留自动自动配置类(工根据pom.xml中写的依赖),
}
流程:
1.它会读取所有的spring.factories文件,读取里面的自动配置类
2.它会继续读取POM依赖里面所包含有的自动配置类,一样是去读该对应包下的spring.factories文件找到里面EnableAutoConfiguration的key,读取所有的自动配置
3.一共127个自动配置类,但是当前程序没有那么多
4.继续筛选,先筛选Exclud排除的自动配置类
5.再根据pom.xml文件里的依赖,对比留下项目所需要的自动配置类
@ComponentScan:扫包,默认是扫描当前其同类同级别的包以及子包
SpringApplicatin初始化方法
SpringBoot启动的时候,会构造一个SpringApplication的实例,构造SpringApplication的时候会进行初始化,初始化的时候会进行以下几件事:
- 把参数sources设置到SpringApplication属性中,这个sources可以是任何类型的参数
- 判断是否是web程序,并设置到webEnvironment的boolean属性中
- 创建并初始化ApplicationInitializer中,设置到Initalizer属性中
- 创建并初始化ApplicationListener,设置到listeners属性中
- 初始化主类mainApplicationClas
总结:将以前的web.xml拉起框架,改为类方法拉起
springBoot启动流程
- 构建一个StopWatch计时器,用来记录SpringBoot的启动时间
- 初始化监听器,获取SpringApplicationRunListeners并启动监听,用于监听run方法的执行
- 创建并初始化ApplicationArguments,获取run方法传递的args参数
- 创建并初始化ConfigurableEnvironment(环境配置).封装main方法的参数,初始化参数,写入到Environment中,发布ApplicationEnvironmentPreparedEvent(环境事件),做一些绑定后返回Environment
- 打印banner版本
- 构造Spring容器(ApplicationContext)上下文.先填充Environment环境和设置的参数,如果application有设置beanNameGenerator(bean),resourceLoader(加载器)就将其注入到上下文中,调用初始化的切面,发布ApplicationContextInitalizedEvent(上下文初始化)时间.
- SpringApplicationRunListeners发布finish事件
- StopWatch计时器停止计时,日志打印总共启动的时间
- 发布SpringBoot程序已启动事件(started())
- 调用ApplicationRunner和CommandLineRunner
- 最后发布就绪事件ApplicationReadEvent,标志着SpringBoot可以处理就收的请求了(running())
注:先进run方法,随后进自动配置
启动器:starter
Starter是什么:
Starter可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成Spring及其他技术,而不需要到处找示例代码和依赖包,如你想使用SpringJPA访问数据库,只要加入spring-boot-starter-data-jpa启动器依赖就能使用了,Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖.
Starters命名:
Spring Boot官方的启动器都是以spring-boot-starter命名的,代表了一个特定的应用类型.第三方的启动器不能以spring-boot开头命名,它们都被Spring boot官方保留,一般一个第三方的应该这样命名,像mvbatis的mvbatis-spring-boot-starter.
自定义starter
以Web应用中常用的验证码为例,一般使用kaptcha类库
- 创建kaptcha-spring-boot-autoconfigure模块,修改pom.xml文件
<properties>
<!--指定项目的源代码版本,此处代码版本为Java8-->
<maven.compiler.source>8</maven.compiler.source>
<!--指定项目的字节码版本,此处代码版本为Java8-->
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 方便IDE能够检测到该依赖中用到的配置属性,能够自动补全,
其实就是在编译的时候在META-INF下面生成了一个spring-configuration-metadata.json文件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 引入@Data等注解,可省略get,set方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 验证码依赖-->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
</dependencies>
- 新建属性类,属性类接收配置文件中配置的属性,可以给属性提供默认值,如下代码
@Data //自动生成getter,setter方法
@Component //实例化为一个bean,并启用spring的自动装配机制
/*
绑定配置属性到到一个类,
(通常与application.properties,application.yml文件中的属性配合使用)
prefix属性用来指定配置属性的前缀
*/
@ConfigurationProperties(prefix='kaptcha')
public class KaptchaProperties{
private int imageWidth = 100; //宽度
private int imageHeight = 40; //高度
private int fontSize = 32; //字体大小
private String fontColor = "0,0,0"; //字符颜色
private String charString = "0123456789"; //显示的字符
private int charLength = 4; //字符数
private String noiseImpl = "com.google.code.kaptcha.impl.NoNoise"; //添加噪声的
}
- 新建配置类,只有Kaptcha类库添加后才需要配置,因而使用注解@ConditionalOnClass
@Configuration //表明这是一个Spring配置类
@Import(KaptchaProperties.class) //导入类,该类包含了Katcha库的配置属性
/*
这个注解指定条件,在类路径中存在类的情况下,这个配置类才会生效
通常用于保证在某些类库或依赖存在才启用相关配置
*/
@ConditionalOnClass(KaptchaServlet.class)
public class KaptchaConfiguration {
//属性类
@Autowired
private KaptchaProperties k;
@Bean
public Producer producer(){
Properties props = new Properties(); //java中用于处理属性的类,通常用于管理配置信息
//使用键值对的形式存储kaptcha库的配置信息
props.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, k.getCharString());
props.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, k.getFontColor());
props.setProperty(Constants.KAPTCHA_NOISE_IMPL, k.getNoiseImpl());
props.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "" + k.getCharLength());
props.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "" + k.getFontSize());
props.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "" + k.getImageHeight());
props.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "" + k.getImageWidth());
//DefaultKaptcha为Kaptcha库的默认实现,用于生成验证码
DefaultKaptcha kaptcha = new DefaultKaptcha();
//在Kaptcha库中,Config类用于配置验证码的生成方式和外观等属性
Config config = new Config(props);
//使用setConfig方法将之前创建的config设置给kaptcha对象
kaptcha.setConfig(config);
//最后,返回配置好了的kaptcha对象
return kaptcha;
}
}
- 新建spring.factories
-
- 在resource目录新建META-INF目录,然后新建spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=配置类在项目中的完全限定名
- 新建模块kaptcha-spring-boot-starter
-
- 新建一个Maven然后删除src,对应的starter项目不需要有src内容,修改pom.xml
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--引入配置的kaptcha-spring-boot-autoconfigure-->
<dependency>
<groupId>org.bdqn</groupId>
<artifactId>kaptcha-spring-boot-autoconfigure</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--生成验证码的库-->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
</dependencies>
- 安装两个模块到本地库
- 新建测试Maven项目,修改pom.xml文件导入配置的kaptcha-spring-boot-starter
<dependency>
<groupId>org.bdqn</groupId>
<artifactId>kaptcha-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
- 新建启动类,配置Controller
@Autowired
private Producer producer;
@GetMapping("/getKaptcha")
public void getKaptcha(HttpSession session, HttpServletResponse response){
//生成验证码文本
String text = producer.createText();
//使用验证码文本生成验证码图像
BufferedImage image = producer.createImage(text);
//将图片存入session作用域中
session.setAttribute("kap",image);
//设置响应内容为"image/png"
response.setContentType("image/png");
try{
//将验证码写入响应的输出流
OutputStream os = response.getOutputStream();
ImageIO.write(image,"png",os);
} catch (IOException e) {
System.out.println("失败");
}
}
- 测试
与传统的引入验证码依赖相比,自定义starter不需要去装配第三方Servlet,减少了配置类代码,也更便于修改Kaptcha的各项属性
SpringBoot配置详解
application.properties配置文件一共可以出现在如下四个位置
- 项目根目录下的config文件夹中(注意是工程的根目录下,不是模块的根目录下)
- 项目根目录下(注意是工程的根目录下,不是模块的根目录下)
- classpath下的config文件夹中
- classpath下
如果4个地方都存在配置文件,会取四个文件的并集,
如果配置出现冲突(出现相同的key),则优先级高的会覆盖优先级低的。
加载的优先级从1到4依次降低
配置文件分类
- properties和yml的优先级(properties的优先级高)
- bootstrap.properties
bootstrap.properties的优先级更高,但在单纯的springboot项目里是不起效果的sprngcloud分布式项目的时候才有用。
从配置文件中获取值
@ConfigurationProperties
- 可以批量的将配置文件中的内容注入到对象中,支持松散绑定
@Component //注册到IOC容器中
@Data //自动生成getter,setter方法
@ConfigurationProperties(prefix = "book")
public class Book {
private String name;
private String author;
}
book.name=三国演义
book.author=罗贯中
@SpringBootTest
public class BookTest {
@Autowired
Book book;
@Test
void testBook(){
System.out.println(book);
}
}
- 使用@ConfigurationProperties和@Bean注解在配置类的Bean定义方法上
QianMo.spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
QianMo.spring.datasource.jdbcUrl=jdbc:mysql:///assay?serverTimezone=Asia/Shanghai
QianMo.spring.datasource.username=root
QianMo.spring.datasource.password=123456
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "QianM.spring.datasource")
DataSource dataSource(){
return DataSourceBuilder.create().build();
}
}
这便是将前缀"QianMo.spring.datasource"的属性,赋值给DataSource对应的属性值
@Configuration注解的配置类中通过@Bean注解在某个方法上将方法返回的对象定义为一个Bean,并使用配置文件中相应的属性初始化该Bean的属性
- 使用@ConfigurationProperties注解普通类,然后通过在启动类中使用@EnableConfigurationProperties定义为bean
@Data
@ConfigurationProperties(prefix = "book")
public class Book {
private String name;
private String author;
}
@SpringBootApplication
@EnableConfigurationProperties(Book.class)
public class Ch501Application {
public static void main(String[] args) {
SpringApplication.run(Ch501Application.class, args);
}
}
使用的时候直接依赖注入就ok @Autowired Book book;
简单类型、对象类型、对象集合、数组类型、map等分别用yml和properties两种写法赋值
@Data
@Component
@ConfigurationProperties("QianMO")
public class TestYml {
private Book book;
private List<Book> books;
private String[] strs;
private Map<String,Object> maps;
}
QianMO:
#对象
book:
name: 水浒传
author: 施耐庵
#list集合
books:
- name: 西游记
author: xxx
- name: 红楼梦
author: yyyy
# strs: ['aaa','bbb']
#数组
strs:
- 'aaa'
- 'bbb'
# maps: {'account': z3, 'realname': 张三}
#map集合
maps:
'account': ls
'realname': 李四
yaml和properties写法自动转换网址
在线yaml转properties-在线properties转yaml-ToYaml.com
SpringBoot配置切换
application.properties一般分为三种:application.properties,application-dev.properties(开发者版本),applicaiton-pro.properties(生产阶段)
使用spring.profiles.active进行版本切换
#切换到生产阶段
spring.profiles.active=pro
@Conditional条件注解
用于条件启用或者禁用@Configuration或则@Bean方法,例如:把默认数据源HikariDataSource换成Druid,那么默认的数据源HikariDataSource对应的bean就不能再配置,否则会出现两个数据源,因而某些bean是否需要注册到spring容器是有 条件的。
@ConditionalOnBean: 系统的ioc容器里如果存在某个bean的情况下才会实例化这个bean
@ConditionalOnClass: 系统中如果存在某个类的情况下,才会实例化一个Bean.
@ConditionalOnExpression: 当表达式为true的时候, 才会实例化一个Bean.
@ConditionalOnMissingBean: 系统的ioc容器里如果不存在某个bean的情况下才会实例化这个bean
@ConditionalOnMissingClass: 系统中如果不存在某个类的情况下,才会实例化一个Bean.
@ConditionalOnNotWebApplication: 不是web应用,才会实例化一个Bean。
@ConditionalOnBean: 当容器中有指定Bean的条件下进行实例化。
@ConditionalohMissingBean: 当容器里没有指定Bean的条件下进行实例化。
@ConditionalOnClass: 当classpath类路径下有指定类的条件下进行实例化。
@ConditionalOnMissingClass: 当类路径下没有指定类的条件下进行实例化。
@ConditionalOnWebApplication: 当项目是一个Web项目时进行实例化。
@ConditionalOnNotWebApplication: 当项目不是一个Web项目时进行实例化。
@ConditionalOnProperty:当指定的属性有指定的值时进行实例化。
@ConditionalOnExpression:基于SpEL表达式的条件判断。
@Condit ionalOnJava:当JVM版本为指定的版本范围时触发实例化。
@ConditionalOnResource:当类路径下有指定的资源时触发实例化。
@ConditionalOnJndi:在JNDI存在的条件下触发实例化。