spring---自定义spring-boot-starter

  在我们的日常开发工作中,经常会有一些独立于业务之外的common模块,特别是现在微服务框架盛行的背景下,我们一个项目往往分成了多个单体项目,而这些单体项目中常会引用公司的一些公共组件,这个时候我们定义Starter,可以使这些单体项目快速搭起,我们只需要关注业务开发。复用的时候只需要将其在pom中引用依赖即可,SpringBoot会为我们完成自动装配,使用起来十分便捷。
在这里插入图片描述

命名规范:

  • 官方命名空间
    前缀:“spring-boot-starter-”
    模式:spring-boot-starter-模块名
    举例:spring-boot-starter-web、spring-boot-starter-actuator、spring-boot-starter-jdbc
  • 自定义命名空间
    后缀:“-spring-boot-starter”
    模式:模块-spring-boot-starter
    举例:mybatis-spring-boot-starter

模块结构:

  在springboot官方文档中,特别提到,我们需要创建两个module ,其中一个是autoconfigure module 一个是 starter module ,其中 starter module依赖 autoconfigure module。但是,这并不是强制规定的大多数开发情况下直接只用一个module写在一起也没有问题,这当然并没有错,这点官方也有说明:

You may combine the auto-configuration code and the dependency management in a single module if you do not need to separate those two concerns
//如果不需要将自动配置代码和依赖项管理分离开来,则可以将它们组合到一个模块中。

实战:

下面实战案例使用一个模块进行创建

热插拔技术:
  在项目中我们经常会在启动类Application上面加@EnableXXX注解,这个@Enablexxx注解就是一种热拔插技术,加了这个注解就可以启动对应的starter,当不需要对应的starter的时候只需要把这个注解注释掉就行,是不是很优雅呢?那么这是如何实现的呢?下面我们拿@EnableAsync注解来看一下其中原理:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AsyncConfigurationSelector.class}) // 关键在@Import
public @interface EnableAsync {
    Class<? extends Annotation> annotation() default Annotation.class;

    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default 2147483647;
}

  在这里最关键的就是@Import({AsyncConfigurationSelector.class})这个点,此时需要将AsyncConfigurationSelector加入到IOC容器。但是如果在我们在关键的自动配置类上@ConditionalOnBean(AsyncConfigurationSelector.class)这个时候会出现什么情况?此时就会出现不加上@EnableAsync注解就无法对关键Bean进行注入,我们的功能就会无法正常开启。 当开启@EnableAsync注解时AsyncConfiguration Selector类就会注入到IOC容器,此时@ConditionalOnBean(AsyncConfigurationSelector.class)条件成立,相对应的自动配置Bean也能相继进行注入。这就是一个简单的实现原理,当然@EnableAsync的实现远不是这么简单,但是总的思想就是通过@Import来实现对bean的控制。在我们想实现类似功能时就可以考虑这种实现思路。

spring-boot-configuration-processor:
  如果你集成了Spring Boot 校验库 ,就会对Properties进行校验。在配置application.yml就会有参数描述,就像java中的注释一样方便我们理解该配置的作用,其实这个就是java注释生成的。你需要依赖下面jar包为我们定义的ConfigurationProperties类生成元信息。

		 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

然后就该依赖会对Properties 成员属性的注释进行提取生成一个spring-configuration-metadata.json文件,这就是配置描述的元数据文件。之后在我们在配置文件中进行输入的时候就会有对应提示,下面是一个简单演示不用在意细节。。。。都是我随便写的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Spring Boot官方也对注释进行了一些规则约束:

不要以“The”或“A”开头描述。
对于boolean类型,请使用“Whether" 或“Enable”开始描述。
对于基于集合的类型,请使用“Comma-separated list”
如果默认时间单位不等同于毫秒,则使用java.time.Duration而不是long描述默认单位,例如“如果未指定持续时间后缀,则将使用秒”。
除非必须在运行时确定,否则不要在描述中提供默认值。

Demo:

下面是一个不健全的模块好多代码都没来得及写仅用于当前演示:
在这里插入图片描述
配置属性类:

@ConfigurationProperties(
        prefix = "business-order"
)
public class BusinessOrderProperties {
    /**
     * hello,hello,hello
     */
    private Boolean vipChannelEnabled = true;
    /**
     * hello,hello,hello
     */
    private int sendMessageTimeout = 3000;
  
  

    public Boolean getVipChannelEnabled() {
        return vipChannelEnabled;
    }

    public void setVipChannelEnabled(Boolean vipChannelEnabled) {
        this.vipChannelEnabled = vipChannelEnabled;
    }

    public int getSendMessageTimeout() {
        return sendMessageTimeout;
    }

    public void setSendMessageTimeout(int sendMessageTimeout) {
        this.sendMessageTimeout = sendMessageTimeout;
    }

}

服务类OrderService ,此类为普通的service,提供给其他服务调用。

public interface OrderService {

    String orderDemo();
}

public class OrderServiceImpl implements OrderService {

    BusinessOrderProperties businessOrderProperties;


    public String orderDemo(){

        return "订单消息推送超时配置" + businessOrderProperties.getSendMessageTimeout();

    }

    public BusinessOrderProperties getBusinessOrderProperties() {
        return businessOrderProperties;
    }

    public void setBusinessOrderProperties(BusinessOrderProperties businessOrderProperties) {
        this.businessOrderProperties = businessOrderProperties;
    }
}

自动配置类:

@Configuration
@EnableConfigurationProperties({BusinessOrderProperties.class})
@ConditionalOnWebApplication
public class BusinessOrderAutoConfiguration {

    @Autowired
    BusinessOrderProperties businessOrderProperties;

    @Bean
    public OrderService orderService(){
        OrderServiceImpl orderService = new OrderServiceImpl();
        orderService.setBusinessOrderProperties(businessOrderProperties);
        return orderService;
    }
}

在resources文件夹下创建META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
vip.chihai.common.order.config.BusinessOrderAutoConfiguration

接下来就可以打包安装到本地仓库进行测试了:
在这里插入图片描述
下面随便找个项目引入下看看是否成功:

  在配置文件中对配置进行修改,将默认3000修改为5000。因为我们之前引入了spring-boot-configuration-processor所以在写配置文件时会有相应提示

business-order:
  send-message-timeout: 5000

在这里插入图片描述
控制台成功输出:
在这里插入图片描述
一些常用的条件注解:

@ConditionalOnClass:当类路径classpath下有指定的类的情况下进行自动配置
@ConditionalOnMissingBean:当容器(Spring Context)中没有指定Bean的情况下进行自动配置
@ConditionalOnProperty(prefix = “example.service”, value = “enabled”, matchIfMissing = true),当配置文件中example.service.enabled=true时进行自动配置,如果没有设置此值就默认使用matchIfMissing对应的值
@ConditionalOnMissingBean,当Spring Context中不存在该Bean时。
@ConditionalOnBean:当容器(Spring Context)中有指定的Bean的条件下
@ConditionalOnMissingClass:当类路径下没有指定的类的条件下
@ConditionalOnExpression:基于SpEL表达式作为判断条件
@ConditionalOnJava:基于JVM版本作为判断条件
@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置
@ConditionalOnNotWebApplication:当前项目不是Web项目的条件下
@ConditionalOnWebApplication:当前项目是Web项目的条件下
@ConditionalOnResource:类路径下是否有指定的资源
@ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者在有多个Bean的情况下,用来指定首选的Bean
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值