1-4.约定优于配置设计范式及Spring Boot源码剖析.md
约定优于配置设计范式及Spring Boot源码剖析
[toc]
一、Spring boot应用回顾
1. 约定优于配置
约定优于配置(Convention over Configuration),又称按约定编程,是一种软件设计规范。本质上是对系统、类库或框架中一些东西假定一个大众化合理的默认值(缺省值)。好处:大大减少了配置项
2. spring boot 于spring 关系
spring boot基于spring
4.0设计,支持省去applicationContext.xml;不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性等问题得到了很好的解决
3.SpringBoot主要特性
SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一个依赖中,这样就可以一次性添加到项目的Maven或Gradle构建中;
使编码变得简单,SpringBoot采用 JavaConfig的方式对Spring进行配置,并且提供了大量的注解,极大的提高了工作效率。
自动配置:SpringBoot的自动配置特性利用了Spring对条件化配置的支持,合理地推测应用所需的bean并自动化配置他们;
使部署变得简单,SpringBoot内置了三种Servlet容器,Tomcat,Jetty,undertow.我们只需要一个Java的运行环境就可以跑SpringBoot的项目了,SpringBoot的项目可以打成一个jar包。
4.全局配置文件
文件名:
application.properties或者application.yml(可以使用其他,需要配置)
文件位置
注意事项:
- 如果同一个目录下,有application.yml也有application.properties,2.4之前版本默认先读取
application.properties。,2.4及之后默认先读取yml。
- 如果同一个配置属性,在多个配置文件都配置了,默认使用第1个读取到的,后面读取的不覆盖前面读取
到的。
- 创建SpringBoot项目时,一般的配置文件放置在“项目的resources目录下”
使用@ConfigurationProperties批量注入配置文件中属性
实体类上添加@Component;@ConfigurationProperties注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//Person
@Component //生成当前类的实例对象存到IOC容器中
@ConfigurationProperties(prefix = "person") //实现批量注入(set方法)
public class Person {
private int id; //id
private String name; //名称
private List hobby; //爱好
private String[] family; //家庭成员
private Map map;
private Pet pet; //宠物
}
//pet
public class Pet {
// 类型
private String type;
// 名称
private String name;
}配置文件application.properties中配置要注入的信息
或者在文件application.yml中配置
spring boot测试用例
1
2
3
4
5
6
7
8
9
10
11@RunWith(SpringRunner.class)
@SpringBootTest
class MySpringbootApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
5.属性注入
@Value单个属性注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14@Configuration//配置类,自动注入到IOC容器
public class JdbcConfiguration {
@Value("${jdbc.url}")
String url;
@Value("${jdbc.driverClassName}")
String driverClassName;
@Value("${jdbc.username}")
String username;
@Value("${jdbc.password}")
String password;
}@ConfigurationProperties放到类上批量注入
1
2
3
4
5
6
7
8@Component
@ConfigurationProperties(prefix = "jdbc")
public class JdbcConfiguration {
String url;
String driverClassName;
String username;
String password;
}@ConfigurationProperties放到方法上注入(一般用于第三方对象赋值)
1
2
3
4
5
6
7
8@Configuration
public class MyService {
@ConfigurationProperties(prefix = "another")
@Bean
public AnotherComponent anotherComponent(){
return new AnotherComponent();
}
}在配置文件中,属性是松散绑定的
first-name,firstName,first_name ,FIRSTNAME 都会被识别为一个字符串
6. 日志框架
抽象层:SLF4J
实现层:logback
统一日志框架使用步骤
排除系统中的其他日志框架。
使用中间包替换要替换的日志框架。
导入我们选择的 SLF4J 实现。
使用
1
2Logger logger = LoggerFactory.getLogger(this.getClass());
logger.info("info日志....");配置
1
2
3
4
5
6
7
8
9
10
11
12
13#日志配置
# 指定具体包的日志级别
logging.level.com.lagou=trace
# 指定控制台日志输出格式
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 指定将日志信息输出到指定文件
logging.file.name=my.log
#logging.file.path=/var/log
# 指定文件日志输出格式
logging.pattern.file=%d{yyyy-MM-dd} ======= [%thread]====== %-5level %logger{50} - %msg%n
- 源码:
git clone -b master1 https://gitee.com/idse666666/my-springboot.git
二、源码解析
1. 依赖管理
1-1.为什么导入dependency时不需要指定版本?
spring-boot-starter-parent 通过继承 spring-boot-dependencies 从而实现了SpringBoot的版本依
赖管理,所以我们的SpringBoot工程继承spring-boot-starter-parent后已经具备版本锁定等配置了,这也
就是在 Spring Boot 项目中部分依赖不需要写版本号的原因
1-2.spring-boot-starter-parent父依赖启动器的主要作用是进行版本统一管理,那么项目运行依赖的JAR包是从何而来的?
spring-boot-starter-web依赖启动器的主要作用是打包了Web开发场景所需的底层所有依赖(基于依赖传递,当前项目也存在对应的依赖jar包)
2.自动配置
2-1.Spring Boot到底是如何进行自动配置的,都把哪些组件进行了自动配置?
@SpringBootApplication:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan组合而成
@SpringBootConfiguration:SpringBoot 的配置类,标注在某个类上,表示这是一个 SpringBoot的配置类。
@EnableAutoConfiguration:Spring 中有很多以 Enable 开头的注解,其作用就是借助 @Import 来收集并注册特定场景相关的
Bean ,并加载到 IOC 容器。
- @Import:遍历各个组件META-INF目录中所有jar包下的spring.factories文件。收集需要配置的类,然后过滤或排除后装载到ioc容器中
@ComponentScan:主要是从定义的扫描路径中,找出标识了需要装配的类自动装配到spring 的bean容器中。
三、自定义starter
- SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。
- 将独立于业务代码之外的功配置模块封装成一个个starter,复用的时候只需要将其在pom中引用依赖即可,再由SpringBoot为我们完成自动装配
- 动态数据源,登录模块,基于AOP技术实现日志切面
1.SimpleBean
1 |
|
2.MyAutoConfiguration
1 |
|
3.在META-INF下建立spring.factories文件以便扫描到我们要注册的starter
4.优化
- 使用@ConditionalOnBean注解,只有ioc容器中注入了这个类才生效
- 自定义出EnableRegisterServer注解,在其上方使用@Import注解使ioc容器中创建configmarker类实例
5.测试
我们可以在另一项目中使用pom.xml引入
1
2
3
4
5<dependency>
<groupId>com.lagou</groupId>
<artifactId>zdy-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>配置yml
1
2
3simplebean:
id: 1
name: zdy测试注入
6.源码
git clone -b master2 https://gitee.com/idse666666/my-springboot.git
四、动态数据源配置
Spring内置了一个AbstractRoutingDataSource,它可以把多个数据源配置成一个Map,然后,根据不同的key返回不同的数据源。因为AbstractRoutingDataSource也是一个DataSource接口,因此,应用程序可以先设置好key,
访问数据库的代码就可以AbstractRoutingDataSource拿到对应的一个真实的数据源,从而访问指定的数据库
1.实现过程图解:
2.配置两个数据源并注入到RoutingDataSource中:
3.RoutingDataSource中创建子类并重写determineCurrentLookupKey方法
4. 提供set和get方法获取存放在ThreadLocal方式获取当前线程key
5.切面技术调用RoutingDataSourceUtil中的ThreadLocal的setkey
6.源码
git clone -b master3 https://gitee.com/idse666666/my-springboot.git
五、缓存
1.重要概念和注解
Spring Cache 只负责维护抽象层,具体的实现由自己的技术选型来决定。将缓存处理和缓存技术
解除耦合。
每次调用需要缓存功能的方法时,Spring会检查指定参数的指定的目标方法是否已经被调用过,如
果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次
调用直接从缓存中获取。
使用Spring缓存抽象时我们需要关注以下两点:
① 确定那些方法需要被缓存
② 缓存策略
2.@Cacheable
将方法运行的结果进行缓存,以后再获取相同的数据时,直接从缓存中获取,不再调用方法
@Cacheable注解的属性
可用的SpEL表达式见下表:
例:@Cacheable(cacheNames = {“emp”},key = “#id”, condition = “#id > 0”, unless = “#result == null”)
缓存的名字为emp,key为id参数,当id>0,且返回结果不为NULL的数据
3.源码
git clone -b master4 https://gitee.com/idse666666/my-springboot.git