今天平安夜,本来以为会是不醉不归的一晚,却跟兄弟们简单吃了点,回来之后通过写几行代码来平静心情。这些天经历了很多事情,心态有个很大的起伏,这期间得到了一些也失去了一些,这些都不重要了,心安即是归处。做好眼前的事情吧,很多年以后回头来看都只是一些经历,人还是要向前看的,你们说是么?
说好的一切还得继续,太阳明天还会照常升起(虽然最近一直阴天),自己只是在庸人自扰罢了!
还是来继续看看spring-boot的源码吧。
自动配置 auto-configuration
在查看注解SpringBootApplication
的源码时会发现这个注解上面有开启自动配置EnableAutoConfiguration
1
2
3
4
5
6
7
8
9
10
11 (ElementType.TYPE)
(RetentionPolicy.RUNTIME)
(excludeFilters = {
.class), (type = FilterType.CUSTOM, classes = TypeExcludeFilter
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
启用了EnableAutoConfiguration`注解之后,springboot 会自动”猜“你想要做哪些事情,例如如果是web程序,他会猜你需要启动tomcat、然后启动监听,如果你引入了MysalDataSource,那就猜需要连接mysql数据库,并且默认的使用localhost:3306的连接信息来尝试连接。
那springboot怎么知道我们在哪些时候加载配置呢?答案就在Condtion系列注解
Condition
Condition系列注解包含了一系列判断条件,例如ConditionalOnClass,意思是告诉程序在只有存在某类时该配置才会生效。
其中包含:
@ConditionalOnClass和@ConditionalOnMissingClass
ConditionalOnBean和ConditionalOnMissingBean
@ConditionalOnProperty
@ConditionalOnResource
@ConditionalOnWebApplication和@ConditionalOnNotWebApplication
@ConditionalOnExpression注释允许基于一个的结果被包括配置使用SpEL表达
当然使用最多的就是ConditionalOnClass和ConditionalOnMissingClass
spring.factories
springboot 会检查所有jar包下的META-INF/spring.factories
文件,这个文件中EnableAutoConfiguration
的KEY下面罗列了需要自动配置的类,例如:1
2
3# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
上述的MybatisAutoConfiguration类的代码是:
1 | .springframework.context.annotation.Configuration |
其中MybatisProperties中可以看到我们经常在application.properties或者application.yml里的配置:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 (prefix = MybatisProperties.MYBATIS_PREFIX)
public class MybatisProperties {
public static final String MYBATIS_PREFIX = "mybatis";
/**
* Location of MyBatis xml config file.
*/
private String configLocation;
/**
* Locations of MyBatis mapper files.
*/
private String[] mapperLocations;
/**
* Packages to search type aliases. (Package delimiters are ",; \t\n")
*/
private String typeAliasesPackage;
/**
* Packages to search for type handlers. (Package delimiters are ",; \t\n")
*/
private String typeHandlersPackage;
/**
* Indicates whether perform presence check of the MyBatis xml config file.
*/
private boolean checkConfigLocation = false;
/**
* Execution mode for {@link org.mybatis.spring.SqlSessionTemplate}.
*/
private ExecutorType executorType;
/**
* Externalized properties for MyBatis configuration.
*/
private Properties configurationProperties;
/**
* A Configuration object for customize default settings. If {@link #configLocation}
* is specified, this property is not used.
*/
private Configuration configuration;
最后做的总结就是
auto-configuration
就是一个实现了Configuration
接口的类。使用@Conditional
注解来限制何时让auto-configuration
生效,通常auto-configuration
使用ConditionalOnClass
和ConditionalOnMissingBean
注解,这两注解的确保只有当我们拥有相关类的时候使得@Configuration
注解生效。
创建自定义的starter
一个完整的Spring Boot starter应该包含下面这些组件:
- autoconfigure 模块包含了自动配置的代码
- starter模块提供了一个autoconfigure的模块和其他额外的依赖。
所以我决定下一篇将带领大家动手自己写一个starter,这个starter来实现一些自动配置的功能。