内容简介:我们在使用 Spring Boot 的过程中,往往都是在pom.xml里加了一系列的依赖,然后启支一个包含main方法的Application,一切就OK啦。给你我的感觉,就像是那我们详细看下,这份「包装好」的原料中,到底做了些什么。这里添加的依赖,除了我们之前在Maven中熟悉的之外,还有一些都是长这个样子:
我们在使用 Spring Boot 的过程中,往往都是在pom.xml里加了一系列的依赖,然后启支一个包含main方法的Application,一切就OK啦。给你我的感觉,就像是 自己要动手做个菜,自己不再需要准备每一部分的原材料,直接购买包装好的一份菜的原料,下锅即可 。
那我们详细看下,这份「包装好」的原料中,到底做了些什么。
添加Starter依赖
这里添加的依赖,除了我们之前在Maven中熟悉的之外,还有一些都是长这个样子:
名为xxx-starter,比如
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version></dependency>复制代码
具体这些starter是怎么起作用的呢,他们什么时候开始工作的?
一切都要从入口处说起。我们以上面的starter为例,看到这个mybatis的starter,其对应的pom中,包含这些依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> </dependency> </dependencies>复制代码
我们看到,相当于我们添加了一个Starter的依赖,其背后会引入许多其定义的其他依赖,通过 Maven 的传递依赖,这些都会被自动添加了进来。
自动配置
相比传统的依赖,我们看到其中包含这样一个: mybatis-spring-boot-autoconfigure
,这也是每个Starter的秘密所在:「AutoConfigure」
它会在实现时,考虑应用中的其他部分因素,「推断」你所需要的 Spring 配置。
在Spring Boot中,我们最大的感受是配置仿佛都被做好了,直接使用即可,这就是
spring-boot-autoconfigure
. 每个starter都有一个名为
spring.factories
的文件,存放在META-INF目录下,其中的内容类似下面这个样子:
# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration复制代码
所有需要自动配置的Class,都需要配置成key是 EnableAutoConfiguration
的。
我们来看类的内部
@Configuration@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})@ConditionalOnBean({DataSource.class})@EnableConfigurationProperties({MybatisProperties.class})@AutoConfigureAfter({DataSourceAutoConfiguration.class})public class MybatisAutoConfiguration {复制代码
Class 之上, 有不少注解来标识,有几点需要关注的:
-
其中有标准的 Spring 配置 注解
@Configuration
-
几个
@ConditionalXX
-
标识执行顺序的
@AutoConfigureAfter
其中, @ConditionalOnClass
标识 SqlSessionFactory
类存在时,执行该配置, @ConditionalOnBean
标识 DataSource
Bean 在 Spring Context时,执行配置。
这些 spring.factories
是怎么被识别的呢? 这就得夸下 Spring 的 FactoriesLoader
了。
看下官方文档说明
Auto-configuration classes are regular Spring {@link Configuration} beans. They are located using the {@link SpringFactoriesLoader} mechanism (keyed against this class). Generally auto-configuration beans are {@link Conditional @Conditional} beans (most often using {@link ConditionalOnClass @ConditionalOnClass} and {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations).
启动的时候,根据ClassLoader中的jar,扫描所有 spring.factories
,将其中符合条件的过滤出来,执行对应的配置。重点可以关注下
AutoConfigurationImportFilter
类,
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() { return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader); }复制代码
private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) { long startTime = System.nanoTime(); String[] candidates = StringUtils.toStringArray(configurations); boolean[] skip = new boolean[candidates.length]; boolean skipped = false; for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) { invokeAwareMethods(filter); boolean[] match = filter.match(candidates, autoConfigurationMetadata); for (int i = 0; i < match.length; i++) { if (!match[i]) { skip[i] = true; skipped = true; } } } if (!skipped) { return configurations; } List<String> result = new ArrayList<>(candidates.length); for (int i = 0; i < candidates.length; i++) { if (!skip[i]) { result.add(candidates[i]); } } return new ArrayList<>(result); }public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = getAttributes(annotationMetadata); List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = filter(configurations, autoConfigurationMetadata); fireAutoConfigurationImportEvents(configurations, exclusions); return StringUtils.toStringArray(configurations); }复制代码
经过这里的执行之后, filter方法把符合条件的过滤出来了。
创建自定义Starter
经过上面两步,我们大概知道 Starter的工作原理。有时候,我们需要对外提供一些 工具 组件时,也想以 Starter 的形式提供出来,供别人使用。步骤也还算清晰,照葫芦画瓢。
-
先创建自己的模块
-
增加需要用到的依赖
-
创建对应的
AutoConfiguration
类 -
创建
META-INF/spring.factories
文件
此时,就不需要再将 Spring Boot 做为 Parent依赖,在单独的依赖中增加
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.0.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.0.6.RELEASE</version> </dependency>复制代码
AutoConfiguration类也简单,照上面的创建一个
@Configuration@ConditionalOnClass(HelloService.class)public class HelloServiceAutoConfiguration {复制代码
然后,增加文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.demo.HelloServiceAutoConfiguration复制代码
在需要这个服务的地方,直接引入依赖就OK啦。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- ABP开发框架前后端开发系列---(14)基于Winform的ABP快速开发框架
- Java开发人员的Flex开发
- Java开发人员的Flex开发
- 行为驱动开发让开发做正确事
- 让开发者专注于应用开发,OpenCenter 3.0 开发者预览版发布
- 让开发者专注于应用开发,OpenCenter 3.0 开发者预览版发布
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Erlang趣学指南
邓辉、孙鸣 / 人民邮电出版社 / 2016-9-7 / 79.00元
这是一本讲解Erlang编程语言的入门指南,内容通俗易懂,插图生动幽默,示例短小清晰,结构安排合理。书中从Erlang的基础知识讲起,融汇所有的基本概念和语法。内容涉及模块、函数、类型、递归、错误和异常、常用数据结构、并行编程、多处理、OTP、事件处理,以及所有Erlang的重要特性和强大功能。一起来看看 《Erlang趣学指南》 这本书的介绍吧!