哦吼,就这破玩意叫@Enable模块驱动

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 这篇文章我想和你聊一聊 spring的@Enable模块驱动的实现原理。在我们平时使用spring的过程中,如果想要加个定时任务的功能,那么就需要加注解@EnableScheduling,如果想使用异步的功能,那就要加@EnableScheduling注解,其实这类注解就是属于@Enable模块。

大家好,我是三友~~

这篇文章我想和你聊一聊 spring的@Enable模块驱动的实现原理。

在我们平时使用spring的过程中,如果想要加个定时任务的功能,那么就需要加注解@EnableScheduling,如果想使用异步的功能,那就要加@EnableScheduling注解,其实这类注解就是属于@Enable模块。

那么 @Enable模块到底有什么功能?

模块是指具备相同领域的功能组件集合,组合所形成一个独立的单元。比如Web MVC模块、AspectJ代理模块Caching缓存模块,JMX(Java管理扩展)、Async异步处理模块等。所谓模块装配,简而言之就是,通过@EnableXXX注解实现一个开关,这个开关决定是否开启某个功能模块的所有组件的自动化配置。

那么 @EnableXXX注解是如何生效的?

其实@EnableXXX只是一个名字,通过这个名字让人知道实现了什么功能,其实这个注解叫什么名字其实是无所谓的,就算不叫@EnableXXX都行,只不过spring内部都叫@EnableXXX,我们就习惯叫@Enable模块,所以核心不是这个注解,而是注解实现的套路。

接下来我们来说说这个注解功能实现的套路

一般@EnableXXX注解是通过@Import实现具体的功能(@EnableXXX注解上加个@Import注解),@Import才是@EnableXXX起效果的核心功能。@Import大家都知道,就是往容器里面注入一个配置类,但是这个配置类可是有讲究的。

这里我直接上源码,带你看看@Import注解功能是如何实现的。

image.png

@Import注解的功能是在org.springframework.context.annotation.ConfigurationClassParser类processImports方法处理的。接下来我们就来解读一下实现的核心部分。

image.png

首先判断@Import注解导入的是配置类有没有实现ImportSelector接口,实现的话就就调用ImportSelector的selectImports方法,这个方法返回的是一批配置类的全限定名,然后继续解析这些配置类。

image.png

ImportSelector接口的作用其实就是往spring容器中再次注入一批配置类。

如果没有实现ImportSelector接口,那么再判断有没有实现ImportBeanDefinitionRegistrar,有的话就会调用ImportBeanDefinitionRegistrar的registerBeanDefinitions方法,通过名字也可以判断出,其实就是往spring容器注入一些BeanDefinition。

image.png

ImportBeanDefinitionRegistrar的作用其实很简单,就是往spring容器注入一些BeanDefinition。如果不是很清楚BeanDefinition是什么,欢迎查看Spring bean到底是如何创建的?(上)这篇文章,有讲解。

如果这两个接口都没有实现,那么就当时一个普通的配置类进行解析。

读完@Import实现的源码,我们再来总结回顾@Import的作用。

@Import注解,就是导入一个配置类,但是这个配置类分为不同的情况。如果这个配置类实现了ImportSelector接口,那么就会调用selectImports方法的实现,获取一批配置类的全限定名,然后再解析配置类;如果实现了@Import注解导入的配置类实现类ImportBeanDefinitionRegistrar,那么就会调用registerBeanDefinitions方法的实现,这个方法可以往容器中注入BeanDefinition;最后如果都没实现,那么就按照一个普通的配置类来解析。

所以基于这么一套配置类解析的规则,就可以实现往容器中注入一些bean,通过这些bean来完成某块功能的实现。

懂了@Enbale模块驱动的基本原理,接下来我们举个例子,来看看@EnbaleAsync注解是如何实现的。

image.png

@EnbaleAsync注解上通过@Import注解导入了AsyncConfigurationSelector类

接下来我们进入这个类

image.png

一看源码,就发现继承了AdviceModeImportSelector,其实这个类实现了ImportSelector接口,附上源码

image.png

其实这个对于ImportSelector接口的实现就是解析注解的属性,然后拿到一个AdviceMode,再调用一个模板方法selectImports,这个方法主要子类来实现,所以我们来看看AsyncConfigurationSelector的实现。

image.png

这个adviceMode是注解@EnableAaync注解中的属性mode(),你可以自己翻一下,默认是PROXY,所以这个方法其实就是返回ProxyAsyncConfiguration类的全限定名,其实就是往容器中添加了ProxyAsyncConfiguration配置类。

我们进入这个配置类看一下

image.png

其实就是往容器中注入一个AsyncAnnotationBeanPostProcessor,通过名字可以看出这是一个BeanPostProcessor,也就是在bean的生命周期的某个节点来处理@Aysnc注解,如果有不懂BeanPostProcessor的同学可以看看Spring bean到底是如何创建的?(上)和 Spring bean到底是如何创建的?(下)这两篇文章,里面有详细的说明。至于AsyncAnnotationBeanPostProcessor的实现我们就不再继续深究了,有兴趣的同学可以自行点进去看看。

所以说白了,@EnbaleAsync注解的主要作用就是往容器中添加一个可以住了@Async注解的AsyncAnnotationBeanPostProcessor,在bean创建的某个阶段起到作用。

看完@EnableAsync注解的实现,你也可以仿照这个注解的实现来自己实现一个@Enable来实现某个特定的功能。

本文到这里也就结束了。

PS:如果觉得这篇文章对你有帮助,欢迎大家关注公众号三友的java日记、分享、点赞、在看,感谢支持。

往期热门文章推荐

如何去阅读源码,我总结了18条心法

如何写出漂亮代码,我总结了45个小技巧

三万字盘点Spring/Boot的那些常用扩展点

三万字盘点Spring 9大核心基础功能

万字+20张图剖析Spring启动时12个核心步骤

1.5万字+30张图盘点索引常见的11个知识点

两万字盘点那些被玩烂了的设计模式

搜索关注公众号 三友的java日记 ,及时干货不错过,公众号致力于通过画图加上通俗易懂的语言讲解技术,让技术更加容易学习,回复 面试 即可获得一套面试真题。

相关文章
|
7月前
USRP相关报错解决办法
USRP相关报错解决办法
109 1
|
4月前
|
缓存 网络协议 Linux
网工,这10条常用命令,没用过3条的,算我输!
网工,这10条常用命令,没用过3条的,算我输!
|
6月前
每周一坑--2048
每周一坑--2048
|
存储 iOS开发 UED
PhotoKit初用
我们公司做了一个DLNA的投屏软件,但是iOS是不能跨应用访问数据的,所以对于局域网投屏视频和图片需要把图片或者视频写入到应用的沙盒路径下。 在我之前的前辈用的是AssetsLibrary,他是在进入界面之前写入,等到完全都写完了才会去显示。之前拍照的照片大小不是很大,而且手机的存储空间也不大,对于用户来说这么处理完全是没有问题的。但是,后来有用户反馈说在本地媒体界面一直都有那个“菊花转”。后来我们发现可能是用户的本地媒体数据过于大,倒是程序假死。 我们老大说,你把这个功能优化一下,目标就是像微信那样是最好的。后来我们就选用的PhotoKit这个框架。
|
存储 消息中间件 缓存
你管这破玩意叫Pulsar
你管这破玩意叫Pulsar
463 0
你管这破玩意叫Pulsar
|
存储 开发框架 .NET
你管这破玩意叫计算机?
你管这破玩意叫计算机?
135 0
你管这破玩意叫计算机?
|
NoSQL Shell Redis
Redis 中 scan 命令太坑了,千万别乱用!!
原本以为自己对redis命令还蛮熟悉的,各种数据模型各种基于redis的骚操作。但是最近在使用redis的scan的命令式却踩了一个坑,顿时发觉自己原来对redis的游标理解的很有限。所以记录下这个踩坑的过程,背景如下:
3536 1
Redis 中 scan 命令太坑了,千万别乱用!!
|
开发工具 Python
抱歉,Xposed真的可以为所欲为——2.改为OV机型流畅玩耍高帧率王者农药(上)
只需20行代码,利用Xposed Hook掉王者农药王者获取手机系统机型的方法, 改成OV系的系统,以此达到流畅玩耍高帧率的目的。
243 0
|
C++ 开发者 Python
抱歉,Xposed真的可以为所欲为——2.改为OV机型流畅玩耍高帧率王者农药(下)
只需20行代码,利用Xposed Hook掉王者农药王者获取手机系统机型的方法, 改成OV系的系统,以此达到流畅玩耍高帧率的目的。
237 0
|
存储 安全 NoSQL
你管这破玩意儿叫 Token?
你管这破玩意儿叫 Token?