当前位置: 首页>后端>正文

基于Spring的插件化开发方案

概述

前置项目中,经常有定制的需求,如何更优雅实现定制的需求

前置云端拆分第一阶段,是把前置云端的代码拆分,第二阶段的目标是实现前置云端共用一个SDK,如何实现扩展性成了一个问题,我试着给出自己的思考

设计模式

对于一些有可能发生变化的地方,进行封装(关注点分离),应用策略模式、责任链模式等手段进行扩展点设计。

扩展点

Java原生SPI

JAVA SPI = 基于接口的编程+策略模式+配置文件 的动态加载机制

对于Java中的SPI,有如下的约定:

  1. 在META-INF/services/目录中创建以接口全限定名命名的文件该文件内容为Api具体实现类的全限定名
  2. 使用ServiceLoader类动态加载META-INF中的实现类
  3. 如SPI的实现类为Jar则需要放在主程序classPath中
  4. Api具体实现类必须有一个不带参数的构造方法

实际上就是JDK的就是ServiceLoader 会遍历所有jar查找META-INF/services/接口类名 文件,找到后就加载文件中配置的文件进行实例化使用。

Spring的扩展点

SPI实现机制

在Spring中提供了SPI机制,我们只需要在 META-INF/spring.factories 中配置接口实现类名,即可通过服务发现机制,在运行时加载接口的实现类:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration

配置好 spring.factories 文件后,我们就可以通过 SpringFactoriesLoader 动态加载接口实现类了

BeanFactoryPostProcessor接口

BeanFactory生成后,如果想对BeanFactory进行一些处理,该怎么办呢?BeanFactoryPostProcessor接口就是用来处理BeanFactory的。

BeanDefinitionRegistryPostProcessor接口

在Spring容器初始化时,首先会读取应用程序中的配置文件,并解析出所有的Bean定义,然后将这些Bean定义注册到容器中。在这个过程中,BeanDefinitionRegistryProcessor提供了一种机制,允许开发人员在Bean定义注册之前和之后对Bean定义进行自定义处理,例如添加,修改或删除Bean定义等。

Mybatis中org.mybatis.spring.mapper.MapperScannerConfigurer就实现了该方法,在只有接口没有实现类的情况下找到接口方法与sql之间的联系从而生成BeanDefinition并注册。

BeanPostProcessor接口

在Spring容器实例化bean之后,在执行bean的初始化方法前后,允许我们自定义修改新的bean实例,如修改bean的属性,可以给bean生成一个动态代理实例等等。

Spring AOP的底层处理也是通过实现BeanPostProcessor来执行代理包装逻辑的。

AOP

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高开发的效率。

我们一般做活动的时候,一般对每一个接口都会做活动的有效性校验(是否开始、是否结束等等)、以及这个接口是不是需要用户登录。

AOP+设计模式

可配置化

插件化

常见的动态插件的实现方式有 SPI、OSGI 等方案,插件化开发模式正在很多编程语言或技术框架中得以广泛的应用实践,比如大家熟悉的jenkins,docker可视化管理平台rancher,以及日常编码使用的编辑器idea,eclipse等,随处可见的带有热插拔功能的插件,让系统像插了翅膀一样,大大提升了系统的扩展性和伸缩性,也拓展了系统整体的使用价值。

1 模块解耦

实现服务模块之间解耦的方式有很多,但是插件来说,其解耦的程度似乎更高,而且更灵活,可定制化、个性化更好。

2 提升扩展性和开放性

插件化机制让系统的扩展性得以提升,从而可以丰富系统的周边应用生态。

3 方便第三方接入

有了插件之后,第三方应用或系统如果要对接自身的系统,直接基于系统预留的插件接口完成一套适合自己业务的实现即可,而且对自身系统的侵入性很小,甚至可以实现基于配置参数的热加载,方便灵活,开箱即用。

最佳实践

  1. 面向接口编程
  2. 方法粒度足够细(对应一个功能点),方法异常能够区分

https://www.xamrdz.com/backend/3eu1936005.html

相关文章: