场景说明:
为什么需要用到启动器?
有时候我们在许多场景中会用到一些通用的配置操作来处理相应的业务,这些东西,我们都可以将它作为一个自定义的Starter来使用。
创建一个starter的springboot工程,引入了springboot的父类。这个就为启动器工程。
需要创建一个resources/META-INF/spring.factories文件,在SpringBoot启动的时候,会去strater包中寻找启动器的这个文件,根据这里的配置去扫描。类似java的SPI机制。
根据这里指定的内容,去加载AutoConfigure类,然后根据条件注解@Conditional进行自动配置将Bean注入到springcontext上下文中。
这是一个模拟的启动器:
spring.factories中指定了自动配置类:(内容如下)
resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.kiki.ksimplespringboot.StarterAutoConfigure
=================================
启动器被消费:
创建属于自己的SpringBoot项目工程
启动类中的代码实现:
1、先想好,我们的service中要用到的参数定义
然后定义一个配置文件类,会在被消费的时候,从配置文件中拿到数据,映射到这个类中【StarterServiceProperties】
2、定义我们的service类,【Kservice】完成属于我们的核心业务处理类,定义属性,这里的数据可以是从StarterServiceProperties中的数据;
创建一个构造函数,在被实例化的时候,用来初始化数据;
创建一个方法,被应用所调用进行业务操作。这个方法比较核心
3、创建一个自动配置类【StarterAutoConfigure】
引入StarterServiceProperties 的属性定义;完成从应用中配置文件数据映射;这个时候,就拿到了入口配置的数据
再创建一个Kservice对象的方法bean,把StarterServiceProperties 中获取到的属性值传递给service;
package com.kiki.ksimplespringboot; import org.springframework.boot.context.properties.ConfigurationProperties; /** * 编写配置文件 * * @ClassName: StarterServiceProperties * @author kiki * @date 2019年6月14日 * @version: V1.0 */ @ConfigurationProperties("example.service") public class StarterServiceProperties { private String config; public String getConfig() { return config; } public void setConfig(String config) { this.config = config; } } |
package com.kiki.ksimplespringboot; /** * 定义service类,根据在StarterAutoConfigure类中读取配置文件的数据,通过实例化构造函数的方式注入数据, * 完成service应有的业务逻辑; 在应用中就对这个service进行实例化,拿到这个类对象进行具体的业务数据操作。 * * @ClassName: Service * @author kiki * @date 2019年6月14日 * @version: V1.0 */ public class Kservice { private String config; public Kservice(String config) { this.config = config; } public String[] split(String separatorChar) { if (this.config == null || this.config.trim().length() == 0 || separatorChar == null || separatorChar.trim().length() == 0) { return null; } return this.config.split(separatorChar); } } |
package com.kiki.ksimplespringboot; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * AutoConfigure类编写;很关键的一个类; * * * @ClassName: StarterAutoConfigure * @author kiki * @date 2019年6月14日 * @version: V1.0 */ @Configuration @ConditionalOnClass(Kservice.class) @EnableConfigurationProperties(StarterServiceProperties.class) public class StarterAutoConfigure { @Autowired private StarterServiceProperties properties; @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix = "example.service", value = "enable", havingValue = "true") Kservice kservice() { return new Kservice(properties.getConfig()); } } |
resources/META-INF/spring.factories 文件内容 org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.kiki.ksimplespringboot.StarterAutoConfigure |
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> </dependencies> |
接下来我们消费创建的启动类
创建一个应用工程,引入启动类的jar
<dependency>
<groupId>com.kiki</groupId>
<artifactId>simple-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
在配置文件application.properties 中引入我们启动器需要用到的配置信息
example.service.enable=true
example.service.config=kiki,bing,ccc
创建一个test测试类
package com.kiki; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import com.kiki.ksimplespringboot.Kservice; @RunWith(SpringRunner.class) @SpringBootTest public class StraterTest { @Autowired Kservice Kservice; @Test public void itest() { String st[] = Kservice.split(","); for (String string : st) { System.out.println(string); } } } |
启动运行,就能看见输出了哦!如此一来,我们就可以在消费服务里面,获取到组件中的类对象,进行相关操作!
注解说明:
@ConditionalOnClass,当classpath下发现该类的情况下进行自动配置。
@ConditionalOnMissingBean,当Spring Context中不存在该Bean时。
@ConditionalOnProperty(prefix = "example.service",value = "enabled",havingValue = "true"),当配置文件中example.service.enabled=true时。
扩展知识:这里用到条件注解比较多
SpringBoot中的@Conditional注解扩展如下:
@ConditionalOnBean:当容器中有指定的Bean的条件下
@ConditionalOnClass:当类路径下有指定的类的条件下
@ConditionalOnExpression:基于SpEL表达式作为判断条件
@ConditionalOnJava:基于JVM版本作为判断条件
@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
@ConditionalOnMissingBean:当容器中没有指定Bean的情况下
@ConditionalOnMissingClass:当类路径下没有指定的类的条件下
@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径下是否有指定的资源
@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean @ConditionalOnWebApplication:当前项目是Web项目的条件下
资源地址:https://github.com/chenbingqian/ksimplespringboot.git