这篇文章我想和你聊一聊 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注解功能是如何实现的。

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

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

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

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

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

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

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

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

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

@EnbaleAsync注解的是如何起作用的

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

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

接下来我们进入这个类

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

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

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

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

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

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

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

本文到这里也就结束了。

如果我的文章对你有所帮助,还请帮忙点赞、在看、转发一下,你的支持会激励我输出更高质量的文章,码字不易,非常感谢!

如果你想联系我,欢迎关注我的个人的微信公众号三友的java日记,公众号会持续推送优质的技术文章,期待与你一起进步。

最近花了一个月的时间,整理了这套并发编程系列的知识点。涵盖了 volitile、synchronized、CAS、AQS、锁优化策略、同步组件、数据结构、线程池、Thread、ThreadLocal,几乎覆盖了所有的学习和面试场景,如图。

文档获取方式:

链接:https://pan.baidu.com/s/129wZe3ywAUsjOqTU037Kmg
提取码:aps9

看Spring源码不得不会的@Enable模块驱动实现原理讲解的更多相关文章

  1. Spring源码分析(一):从哪里开始看spring源码(系列文章基于Spring5.0)

    概述 对于大多数第一次看spring源码的人来说,都会感觉不知从哪开始看起,因为spring项目源码由多个子项目组成,如spring-beans,spring-context,spring-core, ...

  2. 零基础带你看Spring源码——IOC控制反转

    本章开始来学习下Spring的源码,看看Spring框架最核心.最常用的功能是怎么实现的. 网上介绍Spring,说源码的文章,大多数都是生搬硬推,都是直接看来的观点换个描述就放出来.这并不能说有问题 ...

  3. 如何看Spring源码

    想要深入的熟悉了解Spring源码,我觉得第一步就是要有一个能跑起来的极尽简单的框架,下面我就教大家搭建一个最简单的Spring框架,而且是基于Java Config形式的零配置Spring框架. 首 ...

  4. 慢慢看Spring源码

    1. 要想在java技术上提升一下,不看一下java源码是不行的,jdk源码,框架源码等.但是源码那么多,专门去看源码肯定很枯燥,所以就得一点一点看,坚持下去.有一点心得就记一点,如org.sprin ...

  5. spring源码分析之spring-web web模块分析

    0 概述 spring-web的web模块是更高一层的抽象,它封装了快速开发spring-web需要的基础组件.其结构如下: 1. 初始化Initializer部分 1.1  Servlet3.0 的 ...

  6. spring源码分析之spring-web remoting模块概况及基本概念

    spring-web总体分为三部分:caucho.httpinvoker.jaxws,其总体构造图如下: uml结构: 先看看网上搜索到的上述实现的原理吧:Spring RMI,Hessian/Bur ...

  7. Spring源码窥探之:注解方式的AOP原理

    AOP入口代码分析 通过注解的方式来实现AOP1. @EnableAspectJAutoProxy通过@Import注解向容器中注入了AspectJAutoProxyRegistrar这个类,而它在容 ...

  8. spark2.1源码分析4:spark-network-common模块的设计原理

    spark-network-common模块底层使用netty作为通讯框架,可以实现rpc消息.数据块和数据流的传输. Message类图: 所有request消息都是RequestMessage的子 ...

  9. spring源码分析(一)IoC、DI

    创建日期:2016.08.06 修改日期:2016.08.07 - 2016.08.12 交流QQ:992591601 参考书籍:<spring源码深度解析>.<spring技术内幕 ...

随机推荐

  1. 关于小程序websocket全套解决方案,Nginx代理wss

    需求对话 提问 我在本地web能够使用ws协议去链接websocket,但是小程序不能使用. 回答 由于小程序使用的是SSL加密协议,所以需要使用wss.这里wss与ws的关系就相当于https于ht ...

  2. 小程序完整对接 pingpp支付

    小程序完整对接 pingpp支付 有几个先要条件: 小程序需要企业认证且开通支付功能,个人认证是无法使用支付功能的(小程序微信支付官网) pingpp 本身接入的企业服务器(即商户服务器)并不强制要求 ...

  3. AcWing 1047. 糖果

    题目链接 题目描述: 由于在维护世界和平的事务中做出巨大贡献,Dzx被赠予糖果公司2010年5月23日当天无限量糖果免费优惠券. 在这一天,Dzx可以从糖果公司的 N 件产品中任意选择若干件带回家享用 ...

  4. linux(Ubuntu)安装python

    Linux下安装python 提前安装一个依赖环境 (1)ubuntu/Debian: sudo apt-get install -y gcc make cmake build-essential l ...

  5. springcloud集群测试

    使用ribbon实现负载均衡,访问同一个url,轮询不同的服务提供端,从不同的数据库中取数据.

  6. Codeforces Round #707 (Div. 2)A.英语漏洞 + C.Going Home C题收获不小

    A题英语漏洞 A题传送门: https://codeforces.com/contest/1501/problem/A 其实题目说的很明白, 只是我傻傻的会错了意, 话不多说, 开整. 前两行是说, ...

  7. Fastjson tomcat-dhcp链

    Fastjson tomcat-dbcp链 这条链可直接回显,可以解决fastjson在内网的情况,因为很多实战的时候,fastjson的应用部署在内网,只映射一个端口出来,导致前面学习的jdbcRo ...

  8. 【阿里巴巴Java开发手册1.7.0(嵩山版)】编程规约&MySQL 数据库规约

    阿里巴巴Java开发手册1.7.0(嵩山版) 一.编程规约 (一)命名风格 所有命名不得以下划线和$开始和结束. 所有命名不得以拼音或拼音英文混合. 类名使用UpperCamelCase风格. 方法名 ...

  9. jmeter工具初探

    jmeter工具初探 一.jmeter工具介绍 1.一种免费的java开源工具,可以进行二次开发 2.运行环境:java运行环境,需要安装JDK,配置JAVAHOME 环境变量 3.下载jmeter: ...

  10. 携程开源分布式配置系统Apollo服务端是如何实时更新配置的?

    引言 前面有写过一篇<分布式配置中心apollo是如何实时感知配置被修改>,也就是客户端client是如何知道配置被修改了,有不少读者私信我你既然说了client端是如何感知的,那服务端又 ...