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 企业现状分析 压力大:产品需求不明确,上线时间确定,压力山大. 混乱:未立项,开发时间已过半,前期无控制,后期无保障. 疲于应付:开发人员交付的文件质量差,测试跟 ...
随机推荐
- 2019年一半已过,这些大前端技术你都GET了吗?- 下篇
在上一篇文章中已经介绍了大前端关于状态管理.UI组件.小程序.跨平台和框架层的内容.在本文中,我会继续介绍编程语言.工程化.监控.测试和服务端,同时也会对下半年大前端可以关注的部分进行展望. 结合个人 ...
- 插入Oracle数据库后返回当前主键id
最近做一个spring版本3.0.4的老项目功能,应用场景要用到插入oracle表后返回主键ID拿来和其他表关联. 用oralce的可以一直用这种处理方式,高兼容低,搜索网上的资料都不能和这个Spri ...
- spring-boot项目的docker集成化部署(一)
目录 spring-boot项目的docker集成化部署 前言 基本思路与方案 基本步骤 准备源码 服务器和基础环境 结语 1. 本文总结: 2. 后期优化: spring-boot项目的docker ...
- 7.源码分析---SOFARPC是如何实现故障剔除的?
我在服务端引用那篇文章里面分析到,服务端在引用的时候会去获取服务端可用的服务,并进行心跳,维护一个可用的集合. 所以我们从客户端初始化这部分说起. 服务连接的维护 客户端初始化的时候会调用cluste ...
- 用JavaScript带你体验V8引擎解析标识符过程
上一篇讲了字符串的解析过程,这一篇来讲讲标识符(IDENTIFIER)的解析. 先上知识点,标识符的扫描分为快解析和慢解析,一旦出现Ascii值大于128的字符或者转义字符,会进入慢解析,略微影响性能 ...
- java多线程基础(一)--sleep和wait的区别
sleep和wait的区别有: 1.这两个方法来自不同的类分别是Thread和Object: 2.最主要是sleep方法没有释放锁,而wait方法释放了锁,使得线程可以使用同步控制块或者方法: 3.w ...
- 【Kubernetes 系列二】从虚拟机讲到 Kubernetes 架构
目录 什么是虚拟机? 什么是容器? Docker Kubernetes 架构 Kubernetes 对象 基础设施抽象 在认识 Kubernetes 之前,我们需了解下容器,在了解容器之前,我们得先知 ...
- React 练习项目,仿简书博客写作平台
Introduction 技术栈:react + redux + react-router + express + Nginx 练习点: redux 连接 react-router 路由跳转 scss ...
- Apex 获取真正的IP地址
代码如下 declare l_ip varchar2(15); begin if OWA_UTIL.GET_CGI_ENV('X-FORWARDED-FOR') is not null then l_ ...
- Springboot源码分析之jar探秘
摘要: 利用IDEA等工具打包会出现springboot-0.0.1-SNAPSHOT.jar,springboot-0.0.1-SNAPSHOT.jar.original,前面说过它们之间的关系了, ...