Starter 是 Spring Boot 中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的 Bean 根据环境( 条件)进行自动配置。使用者只需要依赖相应功能的 Starter,无需做过多的配置和依赖,Spring Boot 就能自动扫描并加载相应的模块。
我们在 Maven 的依赖中加入 spring-boot-starter-web 就能使项目支持 Spring MVC,并且 Spring
Boot 还为我们做了很多默认配置,无需再依赖 spring-web、spring-webmvc 等相关包及做相关配置就能够立即使用起来.
我们来一步步创建一个自己的starter.这样更能体会到starter整个的运行l流程。
创建一个format-spring-boot-starter.用来对对象进行格式化.
第一步:创建一个maven工程.直接使用
quickstart骨架开发即可.
第二步创建FormatProcessor接口.对该接口提供String和JSON 2种方式实现.
FormatProcessor接口
public interface FormatProcessor {
//定义一个格式化的方法
<T> String format(T obj);
}
JsonFormateProcessor
public class JsonFormateProcessor implements FormatProcessor {
@Override
public <T> String format(T obj) {
return "JsonFormatProcessor:"+ JSON.toJSONString(obj);
}
}
StringFormateProcessor
public class StringFormateProcessor implements FormatProcessor {
@Override
public <T> String format(T obj) {
return "StringFormatProcessor:"+Objects.toString(obj);
}
}
第三步:编写配置类FormatAutoConfiguration
@Configuration //表示该类是一个配置类
public class FormatAutoConfiguration {
@Bean
@ConditionalOnMissingClass("com.alibaba.fastjson.JSON")//当没有JSONclass时候加载这个
public StringFormateProcessor stringFormateProcessor(){
return new StringFormateProcessor();
}
@Bean
@ConditionalOnClass(name = "com.alibaba.fastjson.JSON")//当有JSONclass时候加载这个
@Primary // 设置为首选项
public JsonFormateProcessor jsonFormateProcessor(){
return new JsonFormateProcessor();
}
}
第四步:创建HelloFormatTemplate
该类类似于使用的redisTemplate,JdbcTemplate等模板
public class HelloFormatTemplate {
private FormatProcessor formatProcessor;
private HelloProperties helloProperties; //配置属性,使用该starter的使用者在application.yml中进行配置
public HelloFormatTemplate(FormatProcessor formatProcessor, HelloProperties helloProperties) {
this.formatProcessor = formatProcessor;
this.helloProperties = helloProperties;
}
public <T> String doFormate(T obj){
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append("begin:Execute format").append("<br/>");
stringBuilder.append("HelloProperties:").append(formatProcessor.format(helloProperties.getInfo())).append("<br/>");
stringBuilder.append("Obj format result:").append(formatProcessor.format(obj)).append("<br/>");
return stringBuilder.toString();
}
}
第五步:创建HelloAutoConfiguration
@Import(FormatAutoConfiguration.class)
@EnableConfigurationProperties(HelloProperties.class) //加载配置属性
@Configuration
public class HelloAutoConfiguration {
@Bean
public HelloFormatTemplate helloFormatTemplate(HelloProperties helloProperties,
FormatProcessor formatProcessor){
return new HelloFormatTemplate(formatProcessor,helloProperties);
}
}
第六步:创建HelloProperties
@ConfigurationProperties(prefix = HelloProperties.HELLO_FORMAT_PREFIX) //配置属性前缀
public class HelloProperties {
public static final String HELLO_FORMAT_PREFIX="gupao.hello.format";
private Map<String,Object> info;
public Map<String, Object> getInfo() {
return info;
}
public void setInfo(Map<String, Object> info) {
this.info = info;
}
}
第七步骤,resources目录下创建 /META-INF/spring.factories文件.
spring.factories文件内容
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.grpaoedu.autoconfiguration.HelloAutoConfiguration
在这里进行配置后,springboot项目在启动的时候,就会加载到HelloAutoConfiguration这个类,并会加载在这里面配置的bean.
在使用的时候,直接在springboot项目中配置这个starter的maven地址即可.
<dependency>
<groupId>com.grpaoedu</groupId>
<artifactId>format-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
使用方式
@RestController
public class FormatController {
@Autowired
HelloFormatTemplate helloFormatTemplate;
@GetMapping("/format")
public String format(){
User user=new User();
user.setAge(18);
user.setName("Mic");
return helloFormatTemplate.doFormate(user);
}
}
直接使用 @Autowired注入即可.
在使用方这,如果在Pom文件中引入了fastjson,这块使用的就是JsonFormateProcessor.没有配置fastjson使用的就是StringFormateProcessor.
=======================================================================================
在了解完如何自己写一个starter后,我们可以来看看在springboot中提供的starter都是怎么做的.
首先我们可以开看看JdbcTemplateAutoConfiguration
@Configuration //表示为配置类
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class }) //当拥有这两个类的时候才会进行初始化
@ConditionalOnSingleCandidate(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)//在DataSourceAutoConfiguration初始化完之后在进行
@EnableConfigurationProperties(JdbcProperties.class)//配置属性
public class JdbcTemplateAutoConfiguration {
@Bean
@Primary
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(this.dataSource);
JdbcProperties.Template template = this.properties.getTemplate();
jdbcTemplate.setFetchSize(template.getFetchSize());
jdbcTemplate.setMaxRows(template.getMaxRows());
if (template.getQueryTimeout() != null) {
jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
}
return jdbcTemplate;
}
在这里面初始化了JdbcTemplate.所以,我们在项目中的applicaiotn.properties/application.yml中进行一些简单的属性配置就可以使用JdbcTemplate了.
既然提到了JdbcTemplate.在项目中我们多数时候会有需要操作多个数据源的需求.我们顺便来看看在springboot中如何实现多个数据源.
首先我们可以在配置文件中,自定义配置数据性.
app.datasource.db1.url=jdbc:mysql://127.0.0.1:3306/gp-vip-spring-db-2018
app.datasource.db1.username=root
app.datasource.db1.password=root
app.datasource.db1.driver-class-name=com.mysql.jdbc.Driver
app.datasource.db2.url=jdbc:mysql://127.0.0.1:3306/gp-vip-spring-db-2019
app.datasource.db2.username=root
app.datasource.db2.password=root
app.datasource.db2.driver-class-name=com.mysql.jdbc.Driver
第二步.进行数据源的配置JdbcDataSourceConfig
@Configuration
public class JdbcDataSourceConfig {
/*@Primary*/
@Bean
@ConfigurationProperties(prefix = "app.datasource.db1")
public DruidDataSource db1DataSource(){
// return db1DataSourceProperties().initializeDataSourceBuilder().build();
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setName("db1");
return druidDataSource;
}
@Bean
@ConfigurationProperties(prefix = "app.datasource.db2")
public DataSource db2DataSource(){
// return db2DataSourceProperties().initializeDataSourceBuilder().build();
// return db1DataSourceProperties().initializeDataSourceBuilder().build();
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setName("db2");
return druidDataSource;
}
@Bean(name="db1JdbcTemplate")
public JdbcTemplate db1JdbcTemplate(){
return new JdbcTemplate(db1DataSource());
}
@Bean(name="db2JdbcTemplate")
public JdbcTemplate db2JdbcTemplate(){
return new JdbcTemplate(db2DataSource());
}
}
如果我不在这里配置@Primary的话,则需要在项目的启动类中移除DataSourceAutoConfiguration的自动装配
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class
})
public class SpringBootStatDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootStatDemoApplication.class, args);
}
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootStatDemoApplicationTests {
@Test
public void contextLoads() {
// System.out.println(dataSource.getClass());
}
@Autowired
JdbcTemplate db1JdbcTemplate;
@Autowired
JdbcTemplate db2JdbcTemplate;
/*
@Autowired
DataSource dataSource;*/
@Test
public void addDataData() {
String sql = "insert into user_info(name,age) values('sdasdf',18)";
db2JdbcTemplate.execute(sql);
db1JdbcTemplate.execute(sql);
}
}
=======================================================================================