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 企业现状分析 压力大:产品需求不明确,上线时间确定,压力山大. 混乱:未立项,开发时间已过半,前期无控制,后期无保障. 疲于应付:开发人员交付的文件质量差,测试跟 ...
随机推荐
- kube-proxy源码分析
kubernetes离线安装包,仅需三步 kube-proxy源码解析 ipvs相对于iptables模式具备较高的性能与稳定性, 本文讲以此模式的源码解析为主,如果想去了解iptables模式的原理 ...
- django drf框架中的user验证以及JWT拓展的介绍
登录注册是几乎所有网站都需要去做的接口,而说到登录,自然也就涉及到验证以及用户登录状态保存,最近用DRF在做的一个关于网上商城的项目中,引入了一个拓展DRF JWT,专门用于做验证和用户状态保存.这个 ...
- [转载]MongoDB管理基础
1. 启动和停止MongoDB: 执行mongod命令启动MongoDB服务器.mongod有很多可配置的选项,我们通过mongod --help可以查看所有选项,这里仅介绍一些主要选项: - ...
- 使用DOM4J 对xml解析操作
参考自:https://blog.csdn.net/redarmy_chen/article/details/12969219 dom4j是一个Java的XML API,类似于jdom,用来读写XML ...
- js动态添加<tr><td>
<form id="addNewsFormData" name="addNewsFormData" isCheck="true" ac ...
- 《机器学习基石》---VC维
1 VC维的定义 VC维其实就是第一个break point的之前的样本容量.标准定义是:对一个假设空间,如果存在N个样本能够被假设空间中的h按所有可能的2的N次方种形式分开,则称该假设空间能够把N个 ...
- 5.MySQL数据库操作步骤
第一步:登录到MySQL服务器 第二步:选择当前要操作的数据库 第三步:设置请求和返回数据的字符集 第四步:执行SQL语句 l 增加记录:INSERT INTO news(title,content) ...
- gin+vue的前后端分离开源项目
该项目是gin+vue的前后端分离项目,使用gorm访问MySQL,其中vue前端是使用vue-element-admin框架简单实现的: go后台使用jwt,对API接口进行权限控制.此外,Web页 ...
- python学习笔记(3)--函数、参数、变量、递归
1.函数基本语法和特性 背景摘要 现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏出了所有的知识量吗,写出了以下代码 whi ...
- RANSAC简史
前言 在进行泡泡机器人[图灵智库]栏目的翻译的过程中,我发现在2018-2019的顶会中,依然有很多文章(我看到的不少于6篇)对RANSAC进行各种改进,这令我感到很吃惊.毕竟该方法在1981年就被提 ...