1、Spring Boot与Redis的整合
在《SpringBoot学习笔记16 - 类的自动装配》的 3.2 段提到,框架需要装配的类存储都记录在spring-boot-autoconfigure
依赖下的spring.factories
文件中,该文件中记录了SpringBoot官方整合的所有三方交互类。以Redis为例,Redis作为一个功能强大的应用,SpringBoot自然不会放弃它,而Redis也不会特意为Java开展整合工作。所以这个整合过程只能由SpringBoot自己实现,并将该类记录到spring.factories文件中以便项目启动时能加载到该类并进行注册。
在spring.factories
中有一个RedisAutoConfiguration
类,通过《SpringBoot学习笔记16 - 类的自动装配》的分析我们知道,该类一定会被Spring容器自动装配。但自动装配了就可以读取到Spring Boot配置文件中Redis相关的配置信息了?这个类与Spring Boot配置文件是怎么建立的联系?
2、MyBatis与Spring Boot的整合
与Redis不同,有些第三方应用属于数据Java附属应用,如MyBatis。他们专门为Java提供功能应用功能。所以为了与SpringBoot交互,Mybatis需要自己整合与SpringBoot的交互。这样的类,在spring-boot-autoconfigure
下的spring.factories
文件中是找不到的,所以我们需要通过在pom.xml
文件中添加对应的依赖:
<dependencies>
...
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
...
</dependencies>
在该依赖内部,我们可以发现它也有个自己的autoconfigure依赖:
<!-- mybatis-spring-boot-starter-1.3.2.pom -->
<dependencies>
...
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-autoconfigure</artifactId>
</dependency>
...
</dependencies>
我们查看该依赖明细,找到其spring.factories
文件:
我们进入MybatisAutoConfiguration.java
类中,查看一些我们关心的内容:
@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnBean(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
...
}
@Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
...
}
}
可以看到该类中还包含两个@Bean方法用于创建相应的Bean。
3、自定义Starter
前面两个案例中,无论是 Spring Boot 框架中定义的类,还是三方软件为 SpringBoot 开发的类,都需要导入一个相应的 starter 依赖。那么,如果我们自己的某项功能代码也想将其应用到 Spring Boot 中,为 Spring Boot 项目提供相应支持,需要怎样实现呢?同样,我们需要定义自己的Starter。假设我们现在需要自定义一个Starter去实现如下需求:
为用户提供的字符串添加前辍与后辍,而前辍与后辍定义在 yml 或 properties 配置文件中。例如:
- 前缀:$$$(在application.yml文件中定义)
- 后缀:+++(在application.yml文件中定义)
- 用户输入:China
- 系统输出:$$$China+++
3.1、Starter工程的命名规则
- Spring 官方定义的Starter通常命名遵循的格式为
spring-boot-starter-{name}
例如:spring-boot-starter-web。 - 非 Spring 官方Starter建议命名遵循
{name}-spring-boot-starter
的格式
例如:dubbo-spring-boot-starter。
3.2、创建工程
根据以上命名规则,我们创建一个名为 wrapper-spring-boot-starter
的工程,并导入 Configuration Processor
与 Lombok
依赖。
工程创建完成后,项目结构如下:(不会创建工程?点击这里)
3.3、定义Service类
创建该 Service 类的目的是实现当前 Starter 需要完成的功能。
@AllArgsConstructor
public class WrapService {
private String prefix;
private String suffix;
// 业务核心代码
public String wrap(String word) {
return prefix + word + suffix;
}
}
3.4、定义配置属性封装类
我们创建该类,用于封装来自于 Spring Boot 核心配置文件中的以 some.service 开头的 beore 与 after 属性值。即用于封装配置文件中的如下属性值:some.service.before
、some.service.after
。该类的对象是由系统自动创建,所以无需将其将给 Spring 容器管理。
@Data
@ConfigurationProperties("wrap.service")
public class WrapServiceProperties {
private String prefix;
private String suffix;
}
3.5、定义自动配置类
为自定义配置属性中再添加一个布尔类型的开关属性:some.service.enable
- some.service.enable = true或未设置属性:进行组装
- some.service.enable = false:不进行组装
@Configuration
@ConditionalOnClass(WrapService.class)
@EnableConfigurationProperties(WrapServiceProperties.class)
public class WrapServiceAutoConfiguration {
@Autowired
private WrapServiceProperties properties;
@Bean
@ConditionalOnProperty(name = "wrap.service.enable",
havingValue = "true",
matchIfMissing = true)
public WrapService wrapService() {
return new WrapService(
properties.getPrefix(),
properties.getSuffix()
);
}
/**
* 发现当前实体没有被创建,则创建@Configuration注解
* 是按照代码顺序创建实体的,不能随意修改这其中的顺序,
* 若将该方法放在首位执行,@Configuration很有可能会
* 创建两个实体,这样在启动的时候就会报错
*/
@Bean
@ConditionalOnMissingBean
public WrapService wrapService2() {
return new WrapService("", "");
}
}
3.6、配置spring.factories文件
打开resources/META-INF
目录下名为spring.factories
的文件,若该文件不存在,则创建之。该配置文件是一个键值对文件,键是固定的,为EnableAutoConfiguration
类的全限定性类名,而值则为我们自定义的自动配置类(WrapServiceAutoConfiguration)。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.blairscott.config.WrapServiceAutoConfiguration
4、调用并测试自定义Starter
在本地要使用我们自定义的 Starter,首先要保证其已经被 Install 到了本地 Maven 库。
4.1、创建工程
创建一个Web工程,仅需一个web依赖,过程略。
4.2、在Web项目中导入自定义Starter依赖
<!-- web项目中的pom.xml -->
<dependencies>
...
<dependency>
<groupId>com.blairscott</groupId>
<artifactId>wrapper-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
...
</dependencies>
4.3、定义properties.yml
wrap:
service:
enable: true
prefix: $$$
suffix: +++
4.4、定义Controller
@RestController
public class DemoController {
@Autowired
private WrapService service;
@RequestMapping("/handle/{param}")
public String handle(@PathVariable("param") String param) {
return service.wrap(param);
}
}