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();
}

}
```
![file](https://img2018.cnblogs.com/blog/1747067/201909/1747067-20190910091130214-1566835043.jpg)
#### 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();
}

}
```
![file](https://img2018.cnblogs.com/blog/1747067/201909/1747067-20190910091130769-2137286790.jpg)

Springboot基于enable模块驱动的更多相关文章

  1. 看Spring源码不得不会的@Enable模块驱动实现原理讲解

    这篇文章我想和你聊一聊 spring的@Enable模块驱动的实现原理. 在我们平时使用spring的过程中,如果想要加个定时任务的功能,那么就需要加注解@EnableScheduling,如果想使用 ...

  2. 基于SpringBoot构建分模块项目

    前言 步骤过于详细,多图慎入!!! 假设一个场景,要开发一个4s店维修部的办公系统,其功能有:前台接待,维修抢单,财务结算,库存管理.于是我们创建一个项目balabalabala写完交工. 一段时间后 ...

  3. 如何为编程爱好者设计一款好玩的智能硬件(九)——LCD1602点阵字符型液晶显示模块驱动封装(下)

    六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计 ...

  4. 如何为编程爱好者设计一款好玩的智能硬件(八)——LCD1602点阵字符型液晶显示模块驱动封装(中)

    六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计 ...

  5. 基于Kafka消息驱动最终一致事务(二)

    实现用例分析 上篇基于Kafka消息驱动最终一致事务(一)介绍BASE的理论,接着我们引入一个实例看如何实现BASE,我们会用图7显示的算法实现BASE.

  6. SpringBoot基于数据库实现简单的分布式锁

    本文介绍SpringBoot基于数据库实现简单的分布式锁. 1.简介 分布式锁的方式有很多种,通常方案有: 基于mysql数据库 基于redis 基于ZooKeeper 网上的实现方式有很多,本文主要 ...

  7. 如何分析SpringBoot源码模块及结构?--SpringBoot源码(二)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接 如何搭建自己的SpringBoot源码调试环境?--SpringBoot源码(一). 前面搭建好了自己本地的S ...

  8. IDEA创建SpringBoot的多模块项目教程

    最近在写一个多模块的SpringBoot项目,基于过程总了一些总结,故把SpringBoot多个模块的项目创建记录下来. 首先,先建立一个父工程: (1)在IDEA工具栏选择File->New- ...

  9. 自动化测试架构设计 &&自动化持续集成测试任务实战[线性测试、模块驱动测试、数据驱动测试、关键字驱动测试]

    1 为什么设计自动化测试架构 1.1 企业现状分析 压力大:产品需求不明确,上线时间确定,压力山大. 混乱:未立项,开发时间已过半,前期无控制,后期无保障. 疲于应付:开发人员交付的文件质量差,测试跟 ...

随机推荐

  1. 爬虫环境搭建及 scrapy 启动

    创建虚拟环境 C:\Users\Toling>mkvirtualenv article 这个是普通的创建虚拟环境,但是实际开发中可能会使用python2或python3所以我们需要指定开发的环境 ...

  2. Python基础总结之认识lambda函数、map函数、filter() 函数。第十二天开始(新手可相互督促)

    今天周日,白天在学习,晚上更新一些笔记,希望对大家能更好的理解.学习python~ lambda函数,也就是大家说的匿名函数.它没有具体的名称,也可以叫做一句话函数,我觉得也不过分,大家看下代码,来体 ...

  3. Dubbo源码学习之-服务导出

    前言 忙的时候,会埋怨学习的时间太少,缺少个人的空间,于是会争分夺秒的工作.学习.而一旦繁忙的时候过去,有时间了之后,整个人又会不自觉的陷入一种懒散的状态中,时间也显得不那么重要了,随便就可以浪费掉几 ...

  4. istio入门教程

    广告 | kubernetes各版本离线安装包 安装 安装k8s 强势插播广告 三步安装,不多说 安装helm, 推荐生产环境用helm安装,可以调参 release地址 如我使用的2.9.1版本 y ...

  5. PythonDay04

    ## 第四章 ### 今日内容 - 列表- 元组- range ### 列表 列表相比于字符串,不仅可以储存不同的数据类型,而且可以储存大量数据,是一种可变的数据类型 64位python的限制是 11 ...

  6. Linux下,为应用程序添加桌面图标(ubuntu18.4)

    一.桌面图标位置 Lniux下桌面图标储存路径为:/usr/share/applications 二.桌面图标格式 所有桌面图标格式均为desktop,即名为XXX.desktop 三.编辑内容(常用 ...

  7. java并发编程(五)----(JUC)ReentrantLock

    上一节我们了解了Lock接口的一些简单的说明,知道Lock锁的常用形式,那么这节我们正式开始进入JUC锁(java.util.concurrent包下的锁,简称JUC锁).下面我们来看一下Lock最常 ...

  8. eclipse插件——maven

    项目开发中遇到的问题 都是同样的代码,为什么在我的机器上可以编译执行,而在他的机器上就不行? 为什么在我的机器上可以正常打包,而配置管理员却打不出来? 项目组加入了新的人员,我要给他说明编译环境如何设 ...

  9. CodeForces 526D Om Nom and Necklace

    洛谷题目页面传送门 & CodeForces题目页面传送门 给定字符串\(a\),求它的每一个前缀,是否能被表示成\(m+1\)个字符串\(A\)和\(m\)个字符串\(B\)交错相连的形式, ...

  10. SpringBoot内置tomcat启动原理

    前言          不得不说SpringBoot的开发者是在为大众程序猿谋福利,把大家都惯成了懒汉,xml不配置了,连tomcat也懒的配置了,典型的一键启动系统,那么tomcat在springb ...