Springboot基于enable模块驱动
enable作为模块驱动在Spring Farmework、Spring Boot、Spring Cloud使用,都是通过注解的形式以@enable作为前缀,一些常用注解如
| 框架 | 注解 | 模块 |
| --- | --- | --- |
| Spring Framework | @EnableWebMvc | Web MVC模块 |
| Spring Framework | @EnableTransactionmanagement | Web MVC模块 |
| Spring Framework | @EnableCacheing | Cacheing模块 |
| Spring Framework | @EnableMBeanExport | JMX模块 |
| Spring Framework | @EnableWebFlux | Web Flux模块 |
| Spring Framework | @EnableAspectJAutoProxy | AspectJ模块 |
| Spring Boot | @EnableAutoConfiguration | 自动装配模块 |
| Spring Boot | @EnableWebManagementContext | Actuator模块 |
| Spring Boot | @EnableConfigurationProperties | 配置属性绑定模块 |
| Spring Boot | @EnableOauth2Sso | OAuth2单独登录模块 |
| Spring Cloud | @EnableEurekaServer | eureka服务模块 |
| Spring Cloud | @EnableConfigServer | 配置服务器模块 |
| Spring Cloud | @EnableFeignClients | Feign客户端模块 |
| Spring Cloud | @EnableZuulProxy | 服务网关zuul模块 |
| Spring Cloud | @EnableCircuitBreaker | 服务熔断模块 |
## 如何自定义enable开发?
### 基于ImportSelector实现注解驱动
#### 自定义接入类型
Access为接入类型的接口,下文的RPC接入和REST接入基于这个实现,定义两个接口,一个为启动,一个停止,内部嵌套一个枚举用于标识是哪一种接入
```
public interface Access {
/**
* 初始化配置
*/
void start();
/**
* 销毁配置
*/
void stop();
enum Type{
REST,
RPC
}
}
```
#### 定义RPC和REST的实现
REST实现,只是简单的打印方法
```
public class RestAccess implements Access{
@Override
public void start() {
System.out.println("rest接入配置");
}
@Override
public void stop() {
System.out.println("rest接入销毁配置");
}
}
```
RPC实现
```
public class RpcAccess implements Access{
@Override
public void start() {
System.out.println("rpc接入配置");
}
@Override
public void stop() {
System.out.println("rpc接入销毁配置");
}
}
```
#### 自定义注解EnableAccess
接入类型为RPC或者REST,AccessImportSelector在下一步骤实现
```
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AccessImportSelector.class)
public @interface EnableAccess {
/**
* 接入类型
* @return
*/
Access.Type type();
}
```
#### 实现ImportSelector
定义AccessImportSelector实现ImportSelector,分别获取注解信息,根据注解获取接入类型,根据接入类型选择不同的接入类型
```
public class AccessImportSelector implements ImportSelector{
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//读取EnableAccess中所有的属性方法
Map annotationAttributes = annotationMetadata.getAnnotationAttributes(EnableAccess.class.getName());
//获取属性为type的属性方法
Access.Type type = (Access.Type )annotationAttributes.get("type");
//导入的类名称数组
String [] importClassName = new String[0];
switch (type){
case RPC:
//设置为RPC,返回RpcAccess组件
importClassName = new String[]{RpcAccess.class.getName()};
break;
case REST:
//设置为REST,返回RestAccess组件
importClassName = new String[]{RestAccess.class.getName()};
}
return importClassName;
}
}
```
#### 使用
在primarySource也就是这里的DemoApplication上使用注解EnableAccess,选择接入方式,就会初始化不通的接入组件
```
@SpringBootApplication
@EnableAccess(type=Access.Type.REST)
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
Access access = context.getBean(Access.class);
access.start();
access.stop();
}
}
```
### 基于ImportBeanDefinitionRegistrar实现注解驱动
这里其它步骤一样,主要区别是注解里面Import的类变了,这里是基于基于ImportBeanDefinitionRegistrar实现注解驱动实现
#### 自定义ImportBeanDefinitionRegistrar
```
public class AccessImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
ImportSelector importSelector = new AccessImportSelector();
//筛选class名称集合
String[] selectedClassNames = importSelector.selectImports(annotationMetadata);
Stream.of(selectedClassNames)
.map(BeanDefinitionBuilder::genericBeanDefinition)
.map(BeanDefinitionBuilder::getBeanDefinition)
.forEach(beanDefinition ->{
//注册beanDefinition到beanDefinitionRegistry
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition,beanDefinitionRegistry);
});
}
}
```
#### EnableAccess注解变更
这里import导入了AccessImportBeanDefinitionRegistrar
```
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AccessImportBeanDefinitionRegistrar.class)
public @interface EnableAccess {
/**
* 接入类型
* @return
*/
Access.Type type();
}
```
### 实现
#### RPC接入
type=Access.Type.RPC
```
@SpringBootApplication
@EnableAccess(type=Access.Type.RPC)
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
Access access = context.getBean(Access.class);
access.start();
access.stop();
}
}
```

#### REST接入
type=Access.Type.REST
```
@SpringBootApplication
@EnableAccess(type=Access.Type.REST)
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
Access access = context.getBean(Access.class);
access.start();
access.stop();
}
}
```

Springboot基于enable模块驱动的更多相关文章
- 看Spring源码不得不会的@Enable模块驱动实现原理讲解
这篇文章我想和你聊一聊 spring的@Enable模块驱动的实现原理. 在我们平时使用spring的过程中,如果想要加个定时任务的功能,那么就需要加注解@EnableScheduling,如果想使用 ...
- 基于SpringBoot构建分模块项目
前言 步骤过于详细,多图慎入!!! 假设一个场景,要开发一个4s店维修部的办公系统,其功能有:前台接待,维修抢单,财务结算,库存管理.于是我们创建一个项目balabalabala写完交工. 一段时间后 ...
- 如何为编程爱好者设计一款好玩的智能硬件(九)——LCD1602点阵字符型液晶显示模块驱动封装(下)
六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计 ...
- 如何为编程爱好者设计一款好玩的智能硬件(八)——LCD1602点阵字符型液晶显示模块驱动封装(中)
六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计 ...
- 基于Kafka消息驱动最终一致事务(二)
实现用例分析 上篇基于Kafka消息驱动最终一致事务(一)介绍BASE的理论,接着我们引入一个实例看如何实现BASE,我们会用图7显示的算法实现BASE.
- SpringBoot基于数据库实现简单的分布式锁
本文介绍SpringBoot基于数据库实现简单的分布式锁. 1.简介 分布式锁的方式有很多种,通常方案有: 基于mysql数据库 基于redis 基于ZooKeeper 网上的实现方式有很多,本文主要 ...
- 如何分析SpringBoot源码模块及结构?--SpringBoot源码(二)
注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接 如何搭建自己的SpringBoot源码调试环境?--SpringBoot源码(一). 前面搭建好了自己本地的S ...
- IDEA创建SpringBoot的多模块项目教程
最近在写一个多模块的SpringBoot项目,基于过程总了一些总结,故把SpringBoot多个模块的项目创建记录下来. 首先,先建立一个父工程: (1)在IDEA工具栏选择File->New- ...
- 自动化测试架构设计 &&自动化持续集成测试任务实战[线性测试、模块驱动测试、数据驱动测试、关键字驱动测试]
1 为什么设计自动化测试架构 1.1 企业现状分析 压力大:产品需求不明确,上线时间确定,压力山大. 混乱:未立项,开发时间已过半,前期无控制,后期无保障. 疲于应付:开发人员交付的文件质量差,测试跟 ...
随机推荐
- dubbo文档笔记
配置覆盖关系 以 timeout 为例,显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似: 方法级优先,接口级次之,全局配置再次之. 如果级别一样,则消费 ...
- ns3 802.11b PHY model
I use the ubuntu and do not install the chinse input. The Code: c file requires gnu gsl library, it ...
- Java枚举类型 enum
定义 An enum type is a special data type that enables for a variable to be a set of predefined constan ...
- rpm包制作介绍
RPM(Rpm Package Management)在ReadHat等发行版下被用作软件包管理程序,其将某个软件相关的文件置入一个.rpm包中,用rpm命令,我们可以方便地完成Linux下软件安装. ...
- 使用Prerender.io进行网站预加载
我在自己的项目中是采用的前后端分离的技术,前端用的VUE开发,后端是JAVA开发,tomcat部署,nginx转发,但是VUE开发的项目缺点就是不利于SEO,所以针对SEO做了预加载的操作. 决定采用 ...
- 安全测试基础2-sqlmap演练
sqlmap简介 sqlmap是一个开源的渗透测试工具,可以用来进行自动化检测,利用SQL注入漏洞,获取数据库服务器的权限. 它具有功能强大的检测引擎,针对各种不同类型数据库的渗透测试的功能选项,包括 ...
- 【原创】微信小程序支付java后台案例(公众号支付同适用)(签名错误问题)
前言 1.微信小程序支付官方接口文档:[点击查看微信开放平台api开发文档]2.遇到的坑:预支付统一下单签名结果返回[签名错误]失败,建议用官方[签名验证工具]检查签名是否存在问题.3.遇到的坑:签名 ...
- python骚操作---Print函数用法
---恢复内容开始--- python骚操作---Print函数用法 在 Python 中,print 可以打印所有变量数据,包括自定义类型. 在 3.x 中是个内置函数,并且拥有更丰富的功能. 参数 ...
- ubuntu下部署mongodb以及设置允许远程连接
最近因为项目原因需要在阿里云服务器上部署mongodb,网上查阅了一些资料,特此记录一下步骤 1.运行apt-get install mongodb命令安装mongodb服务(如果提示找不到该pack ...
- Go最火的Gin框架简单入门
Gin 介绍 Gin 是一个 Golang 写的 web 框架,具有高性能的优点,,基于 httprouter,它提供了类似martini但更好性能(路由性能约快40倍)的API服务.官方地址:htt ...