温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何构建Spring源码运行环境

发布时间:2021-06-26 09:31:35 来源:亿速云 阅读:196 作者:chen 栏目:大数据

本篇内容主要讲解“如何构建Spring源码运行环境”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何构建Spring源码运行环境”吧!

为什么研究Spring源码

自己研究源码的初心就是想看看那些牛逼的框架到底是有多牛逼,代码到底有多优雅,怎么利用设计模式去构建程序,如何漂亮实现解耦,如何设计扩展点灵活让第三方开发者干预框架的运行,如何与框架进行整合。说出来可能有人还不信,个人并不是因为想去BAT这些大厂而研究源码,估计像我这个年龄别人也不会要了。。。自嘲一下!

希望自己通过阅读Spring源码提高如下能力:

1.首先肯定是阅读源代码的能力,找到阅读源码的基本方法,提高DEBUG的能力,加强如何定位问题的技巧

2.让自己心里的大象迈出一小步,让自己熟悉阅读源码,培养习惯,以后看更多的源码

3.从源码中找到写出漂亮代码的底层逻辑,比如设计模式、如何解耦、优雅的语法或者API、非常棒的工具类

4.提高项目脚手架质量,提升编码能力,加快BUG定位速度

5.将阅读源码的结果分享出来,尽量可以让路过的人可以产生阅读源码的兴趣,解决工作中遇到问题

构建Spring源码

最新的Spring源码是通过Gradle构建的,因此只接触过Maven构建的朋友建议花几个小时在网上找一个Gradle的学习视频,大概了解一下grovvy和Gradle相关知识,不然真的看不懂gradle.build文件。比如闭包、Gradle特有的API等,还有Gradle的安装、IDEA如何提升Gradle编译速度等。

基于自己的环境写了一篇博客:https://my.oschina.net/u/3049601/blog/3113019 欢迎参考

准备工作

1.简单学习grovvy和Gradle相关知识

2.了解一下设计模式,比如装饰者、模板方法、工厂方法,还有抽象类、接口的运用,里面用了大量的设计模式,不提前了解一下,代码看起来比较吃力

3.学习Java8的Lamda表达式

4.学习Idea的快捷键,DEBUG的一些技巧

如何去看Spring源码

等Spring源码构建完成后,该如何着手去看喃,当然是写一个工程,通过DEBUG Spring源码看执行过程等,总结自己看源码几点经验

1.一定要从GIT上下载源码并构建,反编译看源码,特别是复杂的代码会发蒙的。

2.在工程中开启新的工程或者module,引用项目中的module进行调试

3.看源码之前一定要对框架的使用比较熟悉,千万不要对框架的使用都不熟悉就跑去看源码,那样一定会发蒙的。所以花点钱买点框架使用的书或者视频先看看,不要吝啬那几分钱,等你看完工资一定会涨的。比如SpringMVC,你就只知道加@Controller @Service @Component完成业务代码可不行。

4.看源码时通过DEBUG对框架有总体上的认识,不要一来就往深、细了抠,如果那样的话,你会发现自己很快就看不下去了

5.DEBUG时着重先关注每行代码执行完后关键变量的变化,比如Spring源码当中的beanDefinitionMap singletonObjects beanPostProcessors等,返回的对象或者值是不是可能你需要关注的

6.善用DEBUG的条件断点,否则可能你按了无数次F6也到不了你关注的触发点或者执行点

7.一定要边看边加注释、做笔记、画图什么的,因为一两天你是看不完的,很可能因为其他事情耽搁了,等下次来看又蒙了

8.GOOGLE 百度是常用工具,也可以试着搜索一下gitee或者github上面是否已经有别人看过的源码分析的项目,DOWN下来接着看,可以提高阅读速度,但是一定要写代码去验证,因为有人直接翻译的英文,也许那并没有什么Luan用。既然是看源码,是基本的东西,凡是别人的东西一定要多方面验证才能吸收成正确的自己的,否则看了半天结果是错的就麻烦了。我就遇到了这样的问题,在搜索引擎上找到的内容其实在Spring5已经变了。

Spring大概的工作流程

开始王婆卖瓜。。。。因为现在开发都是基于注解的,因此也是拿AnnotationConfigApplicationContext作为分析对象

概要流程

如何构建Spring源码运行环境

非常概要的图描述Spring容器初始化过程

Spring核心类实例化

    核心类起的作用就好像汽车的发动机,没它都跑不了咯,还能指望它带你去撩妹、看帅哥么。同样,Spring的核心类能够保证容器或者叫上下文能够正常工作,基于它管理我们的业务对象,实现业务逻辑,比如:

    AnnotationConfigApplicationContext:也就是Spring的整个容器,Spring还有另外一个类似的叫ClassPathXmlApplicatonContext(基于XML配置的),在它里面包含了所有实例化的单例Bean、系统参数与配置文件加载后的键值对、后置处理器、每个Bean的定义等等

    AnnotatedBeanDefinitionReader:负责读取被注解修饰了的Bean的定义,并添加到某一个Bean定义的集合当中。典型的场景就是我的ImportResourceAppConfig.class传入到AnnotatedBeanDefinitionReader.register()方法中,在BeanDefinitionMap中会新增一个对应的元素。

    DefaultListableBeanFactory:这个就相当相当重要了。。。它包含了注册BeanDefinition-registerBeanDefinition(),然后利用BeanDefinition获取或者创建Bean的逻辑-getBean(),对应的就有两个方法常使用的四个变量:

        private final Map<String, BeanDefinition> beanDefinitionMap;--存放所有的Spring Bean定义(BeanDefinition),关于BeanDefinition详解查看:https://my.oschina.net/u/3049601/blog/3127635

        private final Map<String, Object> singletonObjects                    --存放所有的单例Spring Bean

        private final Map<String, Object> earlySingletonObjects            --存放循环依赖时需要提前被暴露的Bean,这些Bean并没有被很多PostProcessor(中文翻译为后置处理器)处理,以解决循环依赖不会出现无限制的递归(这里没明白没关系,知道它和解决循环依赖有很重要关系即可,后面会详细说明)

        private final Set<String> singletonsCurrentlyInCreation              --存放当前容器中正在被创建的beanName(它也和循环依赖有很大关系)

核心组件类定义的注册

    图中的就是Bean定义集合的元素截图,这些组件会完成@ComponentScan注解的包扫描,以及被扫描到的类定义注册,实例化裸对象,完成SpringBean的初始化(包含了各种PostProcessor的处理,比如依赖注入)

如何构建Spring源码运行环境

    图中截图Map中Key对应的类如下顺序:

    ConfigurationClassPostProcessor:扫描@ComponentScan中指定包路径下所有符合Spring规则的类,如加了@Configuration @Component等的类,将他们的BeanDefinition注册到beanDefinitionMaps当中。还有另外一个功能就是添加一个ImportAwareBeanPostProcessor,它可以让你的Bean获取到将@Import作为元注解时自定义注解的属性键值对(此功能可以先不管)

    DefaultEventListenerFactory:和Application Event有关,还没详细查看以后再补充

    EventListenerMethodProcessor:和Application Event有关,还没详细查看以后再补充

    AutowiredAnnotationBeanPostProcessor:负责依赖注入和属性注入,比如@Autowired @Value的相应动作

    CommonAnnotationBeanPostProcessor:负责JSR250相关注解的解析与执行,比如@PostContruct @Resource等

注册配置类

    使用AnnotatedBeanDefinitionReader.register(ImportResourceAppConfig.class)将ImportResourceAppConfig的BeanDefinition注册到beanDefinitionMaps当中。完成这个动作之后Spring才能拿到配置类做下一步的包扫描、依赖注入等操作

解析配置类上的注解,并完成BeanDefinition注册

   主要就是ConfigurationClassPostProcessor和AutowiredAnnotationBeanPostProcessor两个类启核心作用(当然还有这两个牵扯出来的其他类),比如ConfigurationClassPostProcessor.ConfigurationClassPaser就是负责完成包扫描的,包含了@ComponentScan @Component @Import @ImportResource @Bean 注解的解析完成所有的BeanDefinition的创建并注册到beanDefinitionMaps当中

根据BeanDefinition实例化Spring Bean

    上一步已经将所有的BeanDefinition准备好,接下来就是遍历他们,使用动态代理完成对象的实例化,并最终得到Spring Bean(可能是裸对象,也可能是代理对象)。

总结:简单的说Spring并不是直接根据Class文件创建一个Bean,而是生成对应的BeanDefinition对象,再根据它创建想要的Bean,在这个过程当中Spring提供了丰富的扩展点去干预BeanDefinition状态和Bean的状态,这些扩展点就是Spring真正强大的原因。

到此,相信大家对“如何构建Spring源码运行环境”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI