SpringBoot——自定义start

更多内容,前往 IT-BLOG

一、Mybatis 实现 start 的原理


首先在写一个自定义的 start 之前,我们先参考下 Mybatis 是如何整合 SpringBoot:mybatis-spring-boot-autoconfigure 依赖包:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>

mybatis 依赖包展示:重要文件:spring.factoriesMybatisAutoConfigurationMybatisProperties

starters 命名:Spring Boot 官方的启动器都是以 spring-boot-starter-命名的,代表了一个特定的应用类型。第三方的启动器不能以 spring-boot开头命名,它们都被 Spring Boot官方保留。一般第三方应该这样命名,像 mybatis 的 mybatis-spring-boot-starter。

 【1】查看 spring.factories 文件:配置自动配置类 MybatisAutoConfiguration。spring.factories 会引导springboot 哪个是自动配置类。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

【2】进入 MybatisAutoConfiguration.class类:下面 @EnableConfigurationProperties(MybatisProperties.class) 引入了配置文件MybatisProperties.class。之后就可以利用这个配置文件里的参数实例化一个对象完成整个 mybatis 的创建。

在 Spring开发过程中我们常使用到 @ConfigurationProperties注解,通常是用来将 properties和 yml配置文件属性转化为 Bean对象使用和修改。在获取这些 Bean之前,首先需要使用 @EnableConfigurationProperties({ConfigBean.class})  注解的作用是开启 @ConfigurationProperties注解,当满足 Condition 条件的时候才执行。

 1 @Configuration
 2 @ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
 3 @ConditionalOnBean({DataSource.class})
 4 /**
 5  * @ConfigurationProperties注解主要用来把properties配置文件转化为bean来使用的,
 6  * 而@EnableConfigurationProperties注解的作用是@ConfigurationProperties注解生效。
 7  * 如果只配置@ConfigurationProperties注解,在IOC容器中是获取不到properties配置文件转化的bean的。
 8  */
 9 @EnableConfigurationProperties({MybatisProperties.class})
10 @AutoConfigureAfter({DataSourceAutoConfiguration.class})
11 public class MybatisAutoConfiguration {
12     private static final Logger logger = LoggerFactory.getLogger(MybatisAutoConfiguration.class);
13     private final MybatisProperties properties;
14     private final Interceptor[] interceptors;
15     private final ResourceLoader resourceLoader;
16     private final DatabaseIdProvider databaseIdProvider;
17     private final List<ConfigurationCustomizer> configurationCustomizers;
18 
19     public MybatisAutoConfiguration(MybatisProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
20         this.properties = properties;
21         this.interceptors = (Interceptor[])interceptorsProvider.getIfAvailable();
22         this.resourceLoader = resourceLoader;
23         this.databaseIdProvider = (DatabaseIdProvider)databaseIdProvider.getIfAvailable();
24         this.configurationCustomizers = (List)configurationCustomizersProvider.getIfAvailable();
25     }
26 //......
27 }

【3】进入 MybatisProperties:这里所有的属性,就是之后我们在 properties 配置文件中配置的项,而@ConfigurationProperties(prefix = "mybatis")定义了前缀。举个栗子:我们一般会在 application.yml 或者 application.properties中 xml 映射文件的路径:mybatis.mapperLocations=classpath:mapping/*.xml 就是以 mybatis 作为前缀的。

mybatis 正是这个 MybatisProperties@ConfigurationProperties 配置的前缀而 mapperLocations 就是我们这个MybatisProperties.class 的其中一个成员变量 !

 1 @ConfigurationProperties(
 2     prefix = "mybatis"
 3 )
 4 public class MybatisProperties {
 5     public static final String MYBATIS_PREFIX = "mybatis";
 6     private String configLocation;
 7     private String[] mapperLocations;
 8     private String typeAliasesPackage;
 9     private String typeHandlersPackage;
10     private boolean checkConfigLocation = false;
11     private ExecutorType executorType;
12     private Properties configurationProperties;
13     @NestedConfigurationProperty
14     private Configuration configuration;
15 
16     public MybatisProperties() {
17     }
18 //......
19 }

【4】现在来看最后一个问题:spring.factories 文件什么时候加载,我们定位到我们的启动类,进入@SpringBootApplication 注解,点进去之后是一个 @EnableAutoConfiguration 注解,再点进去可以看到一个叫做 AutoConfigurationImportSelector.class 的类,就是这里了再点进去,在这个类的源码里搜索 spring.factories

原来springboot 会去 META-INF 目录下找到这个 spring.factories文件,到现在为止我们已经理清楚了整个 start 加载的流程:
【1】去 META-INF 目录下找到这个 spring.factories文件;
【2】通过文件内指定的类路径,找到配置类;
【3】配置类加载进属性类;
【4】配置类通过属性类的参数构建一个新的 Bean;

二、用户自定义 start


就按照这个 Mybatis 的格式,自己写一个 redis 的 start 由于 spring.factories 是指定入口的我们可以放在最后写。下面创建一个普通的 springboot 工程。
【1】编写属性类:添加 @ConfigurationProperties注解和前缀 redis。之后我们就可以在 properties或yml 中 使用 redis.port=指定参数了;

1 @ConfigurationProperties(prefix = "redis")
2 public class RedisProperties {
3     private Integer port;
4     private String host;
5     private String password;
6     private int index;
7     //省略了get set 方法
8 }

【2】编写配置类:添加配置类注解 @Configuration 和加载条件,以及 @EnableConfigurationProperties(RedisProperties.class) 引入属性类,注入到 IOC 容器中。

 1 @Configuration
 2 //只有当Jedis 存在的时候 才执行,就是说一定要引入了Jedis的依赖才会执行这个配置
 3 @ConditionalOnClass(Jedis.class)
 4 //引入属性类
 5 @EnableConfigurationProperties(RedisProperties.class)
 6 public class RedisAutoConfiguration {
 7     @Bean
 8     //当这个bean不存在的时候才执行,防止重复加载bean
 9     @ConditionalOnMissingBean
10     public Jedis jedis(RedisProperties redisProperties) {
11         Jedis jedis = new Jedis(redisProperties.getHost(), redisProperties.getPort());
12         jedis.auth(redisProperties.getPassword());
13         jedis.select(redisProperties.getIndex());
14         return jedis;
15     }
16 }

【3】编写 spring.factories 文件:在 resources 目录下创建入口文件,编写内容:指定配置文件的全路径。随后通过 mvn install 打到本地仓库。

org.springframework.boot.autoconfigure.EnableAutoConfiguration
    =com.yintong.myjedis.RedisAutoConfiguration 

【4】测试:然后我们新建一个 springboot项目,在 pom中加入依赖:

<dependency>
    <groupId>com.yintong</groupId>
    <artifactId>redis-start</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

【5】测试类:@Resource 的作用相当于 @Autowired,只不过 @AutowiredbyType自动注入,而 @Resource默认按 byName自动注入罢了。下面如果你能成功输出就成功了!

 1 @RunWith(SpringRunner.class)
 2 @SpringBootTest
 3 public class TestStartApplicationTests {
 4     @Resource
 5     private Jedis jedis;
 6     @Test
 7     public void contextLoads() {
 8         jedis.set("test","测试成功");
 9         String test = jedis.get("test");
10         System.out.println(test);
11     }
12 }
posted @ 2020-11-18 15:26  Java程序员进阶  阅读(410)  评论(0编辑  收藏  举报