手写一个springBoot-stater(并附加原理详解)

why?

纯属个人缘由。是因为项目开发过程中依赖了各种官方starter,很好奇为什么引入后,其所携带的功能,项目中可以随意使用,而且可添加配置实现个性化、可不添加走默认。
带着好奇直接面向百度,就从好几篇文章中学到了核心思想。

简介boot-starter

boot-starter是boot项目的一个亮点,可降低项目开发中复杂代码量,且节省大量配置,非常符合约定大于配置思想,是一个开箱即用的好组件,在我看来,核心思想也为封装,没什么是封装解决不了的问题,封装大量工具,且提供各式各样的模式选择,使用者只需加点配置即可完美嵌入。

实现原理

相信大家也百度过为啥@SpringBootApplication一个注解这么牛啤,它其中实际上代替了三个注解:@SpringBootConfiguration标记启动类为配置类、@ComponentScan注册启动类同级及子包下的所有bean、@EnableAutoConfiguration自动装配。因此核心就是@EnableAutoConfiguration底层读取spring.factories配置组件的全类名,给IOC容器完成bean注册。

上面提到了spring.factories,该文件就是为了解决jar包中的类加载到容器中的,SpringBoot在SpringFactoriesLoader类中,以硬编码的方式指定了spring.factories这个路径,所以这个文件就是一个扩展点。

说到这里就不得不提Java-Spi机制了。SPI全程Service Provider Interface。为某个接口寻找服务实现。类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。项目中多处有SPI机制的影子,可具体参考文末文章中讲解。

注解学习

//spring工程是否引入了该类 ↓
@ConditionalOnClass
// 配置属性给类↓
@ConfigurationProperties
// 使得@ConfigurationProperties类生效(bean) ↓
@EnableConfigurationProperties
// 保证该bean只有一个 ↓
@ConditionalOnMissingBean
// 当表达式为true的时候,才会实例化这个bean ↓
@ConditionalOnExpression
// 根据属性值决定加不加载 ↓
@ConditionalOnProperty

代码实战

演示说明

该项目仅仅是为了演示新建一个自己的boot-stater,通过自己项目配置可个性化boot-starter的功能,实际上它也广泛应用于-通过配置-为一个接口找到其实现类。

本项目演示:新建一个myjson-spring-boot-stater为了给json序列化成字符串后,加上指定前后缀字符,纯纯演示项目,没有任何实际价值。
注意命名规范:
Spring官方命名:spring-boot-starter-{name}
建议非官方:{name}-spring-boot-starter

实际代码

  1. 新建工程-Pom:
// 新建一个maven工程 myjson-spring-boot-stater`
<dependencies>
    <!-- 自动生成配置元信息文件 -->
    <!-- 其他项目引入该jar后,会自动生成配置文件说明 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
    </dependency>

    <!-- fastJson -->
    <dependency>
        <groupId>com.alibaba.fastjson2</groupId>
        <artifactId>fastjson2</artifactId>
        <version>2.0.1</version>
    </dependency>
</dependencies>
  1. 创建业务类MyJsonService
@Data
public class MyJsonService {
    // 前缀
    private String prefixName;
    // 后缀
    private String suffixName;

    /**
     * 将对象json序列号, 并加上前后缀
     */
    public String objectToMyJson(Object o) {
        return prefixName + JSON.toJSONString(o) + suffixName;
    }
}
  1. 创建配置属性类MyJsonProperties
@Data
@ConfigurationProperties(prefix = "config.json")
public class MyJsonProperties {
    // Starter使用者没在配置文件中配置prefixName属性的值时的默认值
    public static final String DEFAULT_PREFIX_NAME = "Default prefix";

    // Starter使用者没在配置文件中配置suffixName属性的值时的默认值
    public static final String DEFAULT_SUFFIX_NAME = "Default suffix";

    private String prefixName = DEFAULT_PREFIX_NAME;

    private String suffixName = DEFAULT_SUFFIX_NAME;
}
  1. 创建核心配置类MyJsonConfiguration
@Configuration
@ConditionalOnClass(MyJsonService.class)
@EnableConfigurationProperties(MyJsonProperties.class)
public class MyJsonConfiguration {

	@Resource
    private MyJsonProperties myJsonProperties;

    @Bean
    @ConditionalOnProperty(name = "config.json.enable", matchIfMissing = true)
    @ConditionalOnMissingBean(MyJsonService.class)
    public MyJsonService myJsonService() {
        MyJsonService myJsonService = new MyJsonService();
        myJsonService.setPrefixName(myJsonProperties.getPrefixName());
        myJsonService.setSuffixName(myJsonProperties.getSuffixName());
        return myJsonService;
    }
}
  1. 核心-资源resource目录下新建META-INF目录,然后新建spring.factories文件,指定全路径,暴露给项目注册Bean
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
siri.hlb.config.MyJsonConfiguration
  1. 自己项目依赖该jar包, 并添加yml配置
cofig:
  json:
    prefixName: modified-prefix
    suffixName: modified-suffix
    enable: true
  1. 业务中即可直注入使用即可
@Resource
private MyJsonService myJsonService;// 注入
// 直接调用
myJsonService.objectToMyJson(new Object());

学习文章参考:
1. 手写一个boot starter
2. Java中SPI机制
3. springboot自动装配原理

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值