如何实现一个自定义的starter

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: SpringFactoriesLoader加载器加载指定ClassLoader下面的所有的META-INF/spring.factories文件,并将文件解析内容存在Map<string,list>中。然后通过loadFactoryNames传递过来的class的名称从map中获取该类的配置列表。通过Set集合进行去重操作。执行过滤组件操作,而这些操作都是在AutoConfigurationImportFilter接口下的组件实现的,也即FilterSpringBootCondition实现抽象类的。下面有OnBeanCondition、OnClassCondition、OnWebApplic

如果要实现一个自定义的starter,首先需要引入两个依赖spring-boot的jar包:spring-boot-autoconfigure和spring-boot-configuration-processor:

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

在resource中新建META-INF文件夹,创建spring.factories,比如:

#定义自动装配的类=>RedissonCofigurationorg.springframework.boot.autoconfigure.EnableAutoConfiguration=com.study.configuration.RedissonConfiguration

同时你的starter的名称:

<groupId>com.study</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>1.0.0</version>

同时需要基于存在某种条件才进行装配时,可以使用@ContionOnClass.

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented@Conditional(OnClassCondition.class)
public@interfaceConditionalOnClass {
Class<?>[] value() default {};
String[] name() default {};
}

从源码上看,只有在classpath下能找到你需要的conditionOnClass类才会构建这个bean。比如你想写一个redisson的自动装配:

/*** redisson配置:配置、自动配置、配置条件*/@Configuration@EnableConfigurationProperties(value=RedissonProperties.class)
@ConditionalOnClass(RedissonProperties.class)
publicclassRedissonConfiguration {
}

使用@ConditionOnMissingBean:

@ConditionalOnMissingBean,它是修饰bean的一个注解,主要实现的是,当你的bean被注册之后,如果而注册相同类型的bean,就不会成功,它会保证你的bean只有一个,即你的实例只有一个,当你注册多个相同的bean时,会出现异常,以此来告诉开发人员。

通常的相关注解:

@ConditionalOnBean// 当给定的bean存在时,则实例化当前Bean@ConditionalOnMissingBean// 当给定的bean不存在时,则实例化当前Bean@ConditionalOnClass// 当给定的类名在类路径上存在,则实例化当前Bean@ConditionalOnMissingClass// 当给定的类名在类路径上不存在,则实例化当前Bean

创建RessionClient的方式:基于对应的方式创建客户端,因为Ression有很多模式,哨兵、主从、单例、集群、云托管模式,拿到对应的模式的配置后,创建对应的客户端bean:

@Bean@ConditionalOnMissingBean(RedissonClient.class)
publicRedissonClientredissonClient() {
// 创建Redisson客户端对象对象returnRedisson.create(config);
}

同时还需要一些特定的信息:

相关bean:lockAop分布式锁、MQAop发送AOP、RedissonBinary操作对象二进制、RedissonObject操作对象、RedissonCollection操作集合、RedissonClient重要,此时就可以基于@ConditionOnMissBean的方式进行创建,从而实现自定装配。此时可以基于分布式锁Aop切面来做拦截,对分布式锁进行增强操作,也即对当前拿到的锁信息进行判断。对锁的模式进行判断,如果当前的锁模式为自动的,则此时根据你所的key进行判断,如果keys的长度>1,则使用红锁,否者使用可重入式锁。如果锁模式不是联锁&&红锁&&长度大于1,此时会抛异常

如果是公平锁,则直接处理,如果是红锁,则需要变量keys,对锁进行添加到RLock中,对锁进行遍历,添加到数组中,然后将其重新赋值给红锁,否者放入到可重入式锁,或者读锁或者写锁中。执行aop.

那可自动装配又是怎样实现的呢?其关键在于@SpringBootApplication这个注解上,这个组件是一个组合注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented@Inherited@SpringBootConfiguration//springboot配置注解@EnableAutoConfiguration//可以自动注入配置@ComponentScan(excludeFilters= { @Filter(type=FilterType.CUSTOM, classes=TypeExcludeFilter.class),
@Filter(type=FilterType.CUSTOM, classes=AutoConfigurationExcludeFilter.class) }) //进行组件扫描,同时排掉过滤信息public@interfaceSpringBootApplication {
// 省略代码,主要包含的方法:排掉特定自动注入的配置,通过名称或者类方式,进行基包扫描、或者classes、代理bean方法等}

同时我们可以看到SpringBootApplication里面的所有方法,都使用了一个注解@AliasFor。那这个组件有什么用呢?这个注解用于桥接到其它注解,该注解的属性中指定的所桥接的注解类,减少用户使用多注解带来的麻烦。

其关键就在@EnableAutoConfiguration这个注解中,这个注解里面有一个@Import注解,里面这个类自动配置导入选择器类:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented@Inherited@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)
public@interfaceEnableAutoConfiguration {
StringENABLED_OVERRIDE_PROPERTY="spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}

如果我们想使用xml进行配置的话,此时在springboot启动的时候可以使用@Import将配置进行导入,实现配置注入的目的。而AutoConfigurationImportSelector实现了DeferredImportSelector延迟导入选择器,也即ImportSelector的子类。那ImportSelector里面有什么方法呢?里面有两个方法一个是选择导入的方法、一个是排掉过滤的方法,下面可以看到选择导入方法的入参是导入类元数据。

publicinterfaceImportSelector {
String[] selectImports(AnnotationMetadataimportingClassMetadata);
}

那这个选择导入的过程又是怎样的呢?

微信图片_20221214032240.png


SpringFactoriesLoader加载器加载指定ClassLoader下面的所有的META-INF/spring.factories文件,并将文件解析内容存在Map中。然后通过loadFactoryNames传递过来的class的名称从map中获取该类的配置列表。通过Set集合进行去重操作。执行过滤组件操作,而这些操作都是在AutoConfigurationImportFilter接口下的组件实现的,也即FilterSpringBootCondition实现抽象类的。下面有OnBeanCondition、OnClassCondition、OnWebApplicationCondition的getOutcomes方法。

执行fire操作,fireAutoConfigurationImportEvents,此时会执行事件注册。

而其重要的方法就是getAutoConfigurationEntry就是自动装配的重点。



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6月前
|
Java 应用服务中间件 Nacos
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
123 0
|
6月前
|
设计模式 Java 机器人
SpringBoot3自动配置流程 SPI机制 核心注解 自定义starter
SpringBoot3自动配置流程 SPI机制 核心注解 自定义starter
|
架构师 NoSQL Java
【案例实战】SpringBoot3.x自定义封装starter实战
【案例实战】SpringBoot3.x自定义封装starter实战
【案例实战】SpringBoot3.x自定义封装starter实战
|
JSON Java 应用服务中间件
Spring Boot运行原理及功能实现方式
Spring Boot运行原理及功能实现方式
458 0
Spring Boot运行原理及功能实现方式
|
5月前
|
消息中间件 Java Maven
深入理解Spring Boot Starter:概念、特点、场景、原理及自定义starter
深入理解Spring Boot Starter:概念、特点、场景、原理及自定义starter
|
5月前
|
Java Maven
6.自定义starter
6.自定义starter
32 0
|
开发框架 SpringCloudAlibaba Java
Spring Boot自动配置原理详解和自定义封装实现starter
我们一直在强调`Spring Boot`能成为当下主流首选开发框架的主要原因在于其核心思想:**约定大于配置,自动配置,条件装配**。基于这些特性使得`Spring Boot`集成其他框架非常简单快捷
236 1
 Spring Boot自动配置原理详解和自定义封装实现starter
|
消息中间件 缓存 前端开发
Spring Boot自定义启动器的实现原理和实际应用场景?
Spring Boot自定义启动器的实现原理和实际应用场景?
179 0
|
存储 JSON 缓存
Spring自定义参数解析器设计
@RequstBody、@RequstParam 这些注解是不是很熟悉? 我们在开发Controller接口时经常会用到此类参数注解,那这些注解的作用是什么?我们真的了解吗? 简单来说,这些注解就是帮我们将前端传递的参数直接解析成直接可以在代码逻辑中使用的javaBean,例如@RequstBody接收json参数,转换成java对象,如下所示:
114 0
|
机器学习/深度学习 缓存 Prometheus
Spring Boot 框架之自动配置原理、SpringBoot 监控、自定义封装 Starter 启动器等使用指南
Spring Boot 框架之自动配置原理、SpringBoot 监控、自定义封装 Starter 启动器等使用指南
666 0
Spring Boot 框架之自动配置原理、SpringBoot 监控、自定义封装 Starter 启动器等使用指南
下一篇
无影云桌面