京东一面:谈谈你对SpringBoot Starter的理解?

我们使用SpringBoot,基本上都是沉醉在它Starter的方便之中。Starter为我们带来了众多的自动化配置,有了这些自动化配置,我们可以不费吹灰之力就能搭建一个生产级开发环境,有的小伙伴会觉得这个Starter 好神奇呀!其实Starter也都是基于Spring + SpringMVC中的基础知识点实现的,今天小编就通过自定义一个Starter来带大家了解Starter,慢慢揭开Starter的神秘面纱!

其实Starter的核心就是条件注解@Conditional。当classpath下存在某一个Class时,某个配置才会生效,大伙可能也发现了源码解读时总是会出现条件注解,其实这就是Starter配置的核心之一。

1.1Starter定义

所谓的Starter,其实就是一个普通的Maven项目,因此我们自定义Starter,需要首先创建一个普通的Maven项目,然后引入对应的依赖版本,这里我们使用的springboot版本是2.2.1.RELEASE。

# 引入依赖<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>           <groupId>org.springframework.boot</groupId>           <artifactId>spring-boot-starter-parent</artifactId>           <version>2.2.1.RELEASE</version>           <relativePath/>    </parent>    <groupId>com.swk</groupId>    <artifactId>MyStarter</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>MyStarter</name>    <description>MyStarter</description>    <properties>            <java.version>1.8</java.version>    </properties>    <dependencies>          <dependency>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-starter</artifactId>          </dependency>          <dependency>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-starter-test</artifactId>                <scope>test</scope>          </dependency>    </dependencies>    <build>        <plugins>              <plugin>                    <groupId>org.springframework.boot</groupId>                    <artifactId>spring-boot-maven-plugin</artifactId>              </plugin>        </plugins>    </build></project>

依赖引入完成后,我们首先创建一个HelloProperties类,用来接收application.properties中注入的值。

@ConfigurationProperties(prefix = "hello") public class HelloProperties { private static final String DEFAULT_NAME = "隔壁老王";  private static final String DEFAULT_MSG = "隔壁小王"; private String name = DEFAULT_NAME; private String msg = DEFAULT_MSG; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg;}}

这个配置类很好理解,将application.properties中配置的属性值直接注入到这个实例中。

@ConfigurationProperties类型安全的属性注入,即将application.properties文件中前缀为hello的属性注入到这个类对应的属性,最后使用的时候,application.properties中的配置文件,大概如下: ​​​​​​​

hello.name=zhangsan hello.msg=java

配置完成HelloProperties后,接下来我们来定义一个HelloService,然后定义一个简单的say方法,HelloService 的定义如下:​​​​​​​

public class HelloService {   private String msg;   private String name;   public String sayHello() {     return name + " say " + msg + " !";   }   public String getMsg() {     return msg;   }   public void setMsg(String msg) {     this.msg = msg;   }   public String getName() {     return name;  }   public void setName(String name) {     this.name = name;  }}

接下来是重轴戏 - 定义自动配置类​​​​​​​

@Configuration @EnableConfigurationProperties(HelloProperties.class) @ConditionalOnClass(HelloService.class) public class HelloServiceAutoConfiguration {   @Autowired   private HelloProperties helloProperties;   @Bean   public HelloService helloService() {     HelloService helloService = new HelloService();      helloService.setName(helloProperties.getName());     helloService.setMsg(helloProperties.getMsg());     return helloService;   }}

注解说明

@Configuration 注解表明这是一个配置类。

@EnableConfigurationProperties 注 解 是 使 我 们 之 前 配 置 的 @ConfigurationProperties注解生效,让配置的属性成功进入到Bean中。@ConditionalOnClass 表示当项目当前classpath下存在HelloService 时,后面的配置才生效。 

自动配置类中首先注入HelloProperties,这个实例中含有我们在application.properties中配置的相关数据。

创建一个HelloService实例对象,并将HelloProperties中的值注入进去。

到这一步,我们的自动配置类就算是完成了。接下来我们还需要一个spring.factories文件。那么这个文件是干嘛的呢?大家知道我们的SpringBoot项目的启动类都有一个@SpringBootApplication注解,这个注解是一个复合注解,定义如下:​​​​​​​

@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM,classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { }

我们可以看到@SpringBootApplication这是一个组合注解,其中的一个组合项就是@EnableAutoConfiguration,这个注解是干嘛的呢? 

@EnableAutoConfiguration表示启用Spring应用程序上下文的自动配置,该注解会自动导入一个名为AutoConfigurationImportSelector的类,而这个类会去读取一个spring.factories的文件, spring.factories 中则定义需要加载的自动化配置类。

我们打开任意一个框架的Starter,都能看到它有一个spring.factories文件,例如 MyBatis的Starter如下:

那么我们自定义的Starter也需要这样一个文件,我们首先在Maven项目的resources目录下创建一个名为META-INF的文件夹,然后在文件夹中创建一个名为spring.factories的文件,文件内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.swk.mystarter.config.HelloServiceAutoConfiguration

在这里指定我们的自动化配置类的路径即可,如此之后我们的自动化配置类就算完成了。

1.2使用自定义Starter

我们将这个自动化配置类安装到本地仓库,然后在其它项目中使用。安装到本地方式是在IntelliJ IDEA中,点击右边的Maven Project,然后选择 Lifecycle 中的 install,双击即可。

创建SpringBoot工程,在其pom.xml引入自定义Starter工程依赖。

<dependency>  <groupId>com.swk</groupId>  <artifactId>MyStarter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>

引入了自定义的Starter后,我们项目中就有了一个默认的 HelloService 实例可以使用,这里我们直接在单元测试类中注入该实例完成测试。

单元测试

@RunWith(SpringRunner.class) @SpringBootTest public class UsemystarterApplicationTests {     @Autowired    HelloService helloService;    @Test    public void contextLoads() {     System.out.println(helloService.sayHello());    } }

总结

通过上述自定义Starter,相信加深了大家对Starter的理解。我们也可以看到SpringBoot所提供的这种方式主要是基于自动配置来完成的,这种方式在很大程度上减弱了原先Spring框架的配置,体现了SpringBoot框架“约定大于配置”的思想,让我们开发人员更加专注于业务实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值