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工程.直接使用

Spring Boot Starter Security和springboot版本对应 spring boot的starter_springboot


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);
    }
}

=======================================================================================