前言

实现starter,其实就是SpringBoot的自动装配原理的一个实践,以前我也写过SpringBoot的自动状态原理的文章,文章链接

细心认真对待,没有什么是很难的

一、SpringBoot 中的SPI机制

什么是spi呢,全称是Service Provider Interface。简单翻译的话,就是服务提供者接口,是一种寻找服务实现的机制。

其实就是一个规范定义、或者说是实现的标准。

用生活中的例子说就是,你买了一台小米的手机。

但是你用的充电器并不一定非要是小米充电器,你可以拿其他厂商的充电器来进行充电,只要满足协议、端口等要求,那么就是可以充电的。这也是一种热拔插的思想,并不是固定死的。

换成代码来说也是一样的,我定义了一个接口,但是不想固定死具体的实现类,因为那样如果要更换实现类就要改动源代码,这往往是不合适的。

那么我也可以定义一个规范,在之后需要更换实现类或增加其他实现类时,遵守这个规范,我也可以动态的去发现这些实现类。

换在SpringBoot中,就是现在的SpringBoot这个平台定义了一些规范和标准,我现在想要让SpringBoot平台接纳我。

我该如何做呢?

很简单,按照它的标准和规范做事

SpringBoot在启动的时候,会扫描所有jar包resource/META-INF/spring.factories文件,依据类的全限定名,利用反射机制将Bean装载进容器中。

看完这段话,我想你应该对今天的文章应该有个大概的理解啦。

二、自定义 starter

说一说我的小实践:

在这个 starter 中,实现

  • 发送短线的Template
  • 对象存储的Template

的自动装配~

大致就是四步:

  • 用于映射配置文件中的配置的类xxxxProperties
  • 用于操作xxxx的接口和客户端等等,如本文中的OssTemplate
  • 自动配置类xxxxAutoConfiguration ,并且向容器中注入xxxxTemplate
  • 在spring.factories中将xxxxAutoConfiguration添加进EnableAutoConfiguration的vaule集合中

对象存储我用的是阿里云的oss,里面的配置都是可以用的, 短信的话,就是个模拟的啦~,勿怪啦

image.png

2.1、准备一个Maven项目

删除src目录,

然后再创建两个 Maven项目(我个人习惯,习惯创建空Maven项目,实际上创建SpringBoot项目也是一样)

image.png

最外层的pom.xml

 <parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>2.5.2</version>
     <relativePath/>
 </parent>

 <properties>
     <maven.compiler.source>8</maven.compiler.source>
     <maven.compiler.target>8</maven.compiler.target>
 </properties>


 <dependencies>
     <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-configuration-processor</artifactId>
         <optional>true</optional>
     </dependency>
 </dependencies>

2.2、准备Properties类

就是用来映射配置文件的~

 /**
  * @author Ning Zaichun
  */
 @Data
 @ConfigurationProperties(prefix = "nzc.oss")
 public class OssProperties {

     private String accessKey; 
     private String secret;
     private String bucketName;
     private String url;
     private String endpoint;
 }
 @Data
 @ConfigurationProperties(prefix = "nzc.sms")
 public class SmsProperties {

     private String name;
 }

2.3、准备要注入的类

就是我们最后要通过自动装配注入进SpringBoot操作的类

我这里分别是OssTemplate 和 SmsTemplate

 /**
  * @author Ning Zaichun
  */
 public class OssTemplate {

     private OssProperties ossProperties;

     public OssTemplate(OssProperties ossProperties) {
         this.ossProperties = ossProperties;
     }

     public String test() {
         System.out.println(ossProperties.getBucketName());
         return "test";
     }
     public String upload(String filename, InputStream is) {
         // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
         String endpoint = ossProperties.getEndpoint();
         // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
         String accessKeyId = ossProperties.getAccessKey();
         String accessKeySecret = ossProperties.getSecret();

         // 创建OSSClient实例。
         OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

         String storePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date())   "/"   UUID.randomUUID()   filename.substring(filename.lastIndexOf("."));

         System.out.println(storePath);
         // 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。
         ossClient.putObject(ossProperties.getBucketName(), storePath, is);

         String url = ossProperties.getUrl()   storePath;

         // 关闭OSSClient。
         ossClient.shutdown();
         return url   "#"   storePath;
    }

     public void remove(String fileUrl) {
         // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
         String endpoint = ossProperties.getEndpoint();
         // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
         String accessKeyId = ossProperties.getAccessKey();
         String accessKeySecret = ossProperties.getSecret();
         // 填写Bucket名称。
         String bucketName = ossProperties.getBucketName();
         // 填写文件完整路径。文件完整路径中不能包含Bucket名称。
         //2022/01/21/f0870eb3-4714-4fae-9fc3-35e72202f193.jpg
         String objectName = fileUrl;

         // 创建OSSClient实例。
         OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

         // 删除文件或目录。如果要删除目录,目录必须为空。
         ossClient.deleteObject(bucketName, objectName);

         // 关闭OSSClient。
         ossClient.shutdown();
     }
 }
 public class SmsTemplate {

     private SmsProperties properties;

     public SmsTemplate(SmsProperties properties) {
         this.properties = properties;
     }

     public void sendSms(String mobile, String code){
         System.out.println(properties.getName() "==" mobile "====" code);
     }
 }

2.4、AutoConfiguration

 @EnableConfigurationProperties({
     SmsProperties.class,
     OssProperties.class
         })
 public class CommonAutoConfig {

     @Bean
     public SmsTemplate smsTemplate(SmsProperties smsProperties){
         return new SmsTemplate(smsProperties);
     }

     @Bean
     public OssTemplate ossTemplate(OssProperties ossProperties){
         return new OssTemplate(ossProperties);
     }

 }

2.5、编写spring.factories

在resource目录下,创建一个META-INF文件夹,

在META-INF文件夹下创建一个spring.factories文件

内容是

 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
   com.nzc.CommonAutoConfig

如果有多个就是:

 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
   com.nzc.CommonAutoConfig \
   com.xxx.xxx

到这一步之后,我们将这个项目,达成Jar包,然后在要使用的项目中进行引入。

2.6、应用测试

  • 1、创建一个SpringBoot 的启动类,有启动类才能进行测试,不然没上下文环境~
  • 2、编写配置文件
 spring:
   application:
     name: app-server
 nzc:
   sms:
     name: ningzaichun
   oss:
     accessKey: xxx
     secret: xxx
     endpoint: oss-cn-shenzhen.aliyuncs.com
     bucketName: xxx
     url: xxx

将oss的配置修改正确是可以用的~

编写测试类:

 @RunWith(SpringRunner.class)
 @SpringBootTest(classes = AppServerApplication.class)
 public class TemplateTest {

     @Autowired
     private OssTemplate ossTemplate;
     @Test
     public void testOss(){
         String s = ossTemplate.test();
         System.out.println(s);
     }
     @Test
     public void testUpload(){
         try {
             File file = new File("D:\evectionflow01.png");
             InputStream inputStream = new FileInputStream(file);
             ossTemplate.upload("123.jpg",inputStream);
         } catch (FileNotFoundException e) {
             e.printStackTrace();
         }
     }
     @Autowired
     private SmsTemplate smsTemplate;

     @Test
     public void testSendSms(){
         smsTemplate.sendSms("17670090715","123456");
     }
 }

证明是可以使用的~

后记

写得较为简单,也通俗易懂~,应该能明白吧,哈哈,

如果文中有存在错误或者是不对的地方,请留下您的评论,我会及时修正,非常感谢!

这次可能是说点废话,以前我觉得工作三四年的Java开发工作者,应该是会懂很多很多东西。

因为是后端开发吗,很多时候不可避免的要接触到一些其他东西,运维部署、测试、前端、底层、架构什么的,我说的是接触,而不是精通~,不要骂我。只是个人看法。

到此这篇关于SpringBoot SPI 机制和实现自定义 starter的文章就介绍到这了,更多相关SpringBoot SPI内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

SpringBoot SPI 机制和实现自定义 starter的更多相关文章

  1. SpringBoot本地磁盘映射问题

    这篇文章主要介绍了SpringBoot本地磁盘映射问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  2. java SpringBoot 分布式事务的解决方案(JTA+Atomic+多数据源)

    这篇文章主要介绍了java SpringBoot 分布式事务的解决方案(JTA+Atomic+多数据源),文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下

  3. SpringBoot整合Javamail实现邮件发送的详细过程

    日常开发过程中,我们经常需要使用到邮件发送任务,比方说验证码的发送、日常信息的通知等,下面这篇文章主要给大家介绍了关于SpringBoot整合Javamail实现邮件发送的详细过程,需要的朋友可以参考下

  4. SpringBoot详细讲解视图整合引擎thymeleaf

    这篇文章主要分享了Spring Boot整合使用Thymeleaf,Thymeleaf是新一代的Java模板引擎,类似于Velocity、FreeMarker等传统引擎,关于其更多相关内容,需要的小伙伴可以参考一下

  5. Springboot集成mybatis实现多数据源配置详解流程

    在日常开发中,若遇到多个数据源的需求,怎么办呢?通过springboot集成mybatis实现多数据源配置,简单尝试一下,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  6. 一篇文章带你了解vue.js的事件循环机制

    这篇文章主要为大家详细介绍了vue.js事件循环机制,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

  7. SpringBoot使用Minio进行文件存储的实现

    本文主要介绍了SpringBoot使用Minio进行文件存储的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  8. 解析SpringBoot中使用LoadTimeWeaving技术实现AOP功能

    这篇文章主要介绍了SpringBoot中使用LoadTimeWeaving技术实现AOP功能,AOP面向切面编程,通过为目标类织入切面的方式,实现对目标类功能的增强,本文给大家介绍的非常详细,需要的朋友可以参考下

  9. 详解springboot测试类注解

    这篇文章主要介绍了springboot测试类注解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  10. Python超详细讲解内存管理机制

    本章主要介绍Pyhon的内存管理,以Pyhon的计数机制作为引入,介绍Pyhon的内存管理方式,感兴趣的朋友来看看吧

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部