关于spring的源码的理解

从最基础的Hello World开始。

spring的Hello World就三行代码:

public void test() {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    SomeBean someBean= (SomeBean) context.getBean("someBean");
    someBean.doSomething();
}

这个hello world非常简单,通过xml文件,创建一个容器context,然后从容器中获取一个bean。

运行完这段代码后,问自己两个问题:

  • 容器创建时做了什么?
  • getBean()时又做了什么?

虽然这个例子是用的xml配置,但是搞懂这两个问题,对于另外两种配置方式,注解配置和Java Config,也就顺理成章了,原理都一样的。

如何才能知道?调试

好,开始回答第一个问题,容器创建时做了什么?

不管是xml,还是注解、Java Config,这些都是为了方便使用者而设计的,JVM可不知道说<bean>这个标签是啥意思,所以自然的,Spring需要对这些配置进行解析。

比如对于xml,就用XmlBeanDefinitionReader,把你写的beans.xml解析出来,你要创建什么对象,这些对象依赖哪些对象,是不是要懒加载(lazy-init),是不是单例...... 通通解析出来,放到一个叫BeanDefinition的对象里头,有多少种对象,就有多少个BeanDefinition,然后把这些BeanDefinition放到一个Map里头。

BeanDefinition有什么用?当然是为了后面实例化Bean用的,为什么要把配置信息放到BeanDefinition里?自然是不想每次需要实例对象时都去解析配置信息。

创建完所有BeanDefinition之后,会马上实例化对象吗?

如果用的是BeanFactory作为容器,则不会,对象默认都是懒加载,也就是在你想获取的时候再创建;

如果用的是上面hello world里的ApplicationContext ,则会马上实例化所有非懒加载的bean。

怎么实例化呢?这时候BeanDefinition就派上用场了,利用BeanDefinition里面的类信息,再用上反射,很容易就可以new出一个实例;

那如果bean里面依赖其他bean呢?那就顺带把其他bean也实例化出来,然后通过构造函数或者set方法,注入到bean里面去。

实例化后的bean,就直接返回给你了吗?这可不行,单例对象可是要复用的,Spring容器会被new出来的对象,放到又一个Map里面,这也解释了为什么bean不会被GC回收,因为bean通过Map和容器关联了,而容器对象是GC Root。当然,上面讲的仅限于单例,多例可不会放到Map里,容器创建完就直接丢出去了,让对象自生自灭,该回收时就回收。

第一个问题回答结束。

理解了第一个问题,第二个问题就很简单了,获取bean时又做了什么?

很简单:

  • 如果bean是单例,并且还没实例化,那就按照上面的流程new一个,如果已经实例化了,就直接返回;
  • 如果是多例,new一个返回

第二个问题回答结束。

稍微总结一下。怎样读源码?先学会怎么用,再去弄懂为什么。知其然知其所以然,首先要知其然啊。

读源码跟读书很像的,带着疑问去阅读,效率会高很多

  先粗读,也就是不断的单步调试,不必每个方法都step into想一看究竟,多step over,了解一下大概,然后记下疑问,进行第二版精读。

  精读就要弄懂每一行代码吗?不必,只看你关心的,Spring IoC的实际逻辑比我上面讲的要复杂的多,包括一些如果放在bean在实例化的过程中,拒绝掉新的实例化请求等线程安全问题,这些都不是你关心的重点,看到了快速跳过即可,只看你关心的。

对于spring的源码是否要看,观点是:

  建议不要硬着头皮看spring代码,本身的代码800多m,就是不上班开始看也不知道什么时候看完。如果想学学ioc,控制反转这些建议看看jodd项目,比较简练,但是我仍然不建议过多的看这些框架的代码,因为这些代码要完成任务需要很多琐碎的类实现,比如读取某个包下面的所有类,解析class的头文件,反射各种信息,再加上封装,很有可能在读源码的过程中掉到各种细节里出不来,所以读这种源码要事无巨细,理解原理即可。
  基本原理其实就是通过反射解析类及其类的各种信息,包括构造器、方法及其参数,属性。然后将其封装成bean定义信息类、constructor信息类、method信息类、property信息类,最终放在一个map里,也就是所谓的container,池等等,其实就是个map。。汗。。。。当你写好配置文件,启动项目后,框架会先按照你的配置文件找到那个要scan的包,然后解析包里面的所有类,找到所有含有@bean,@service等注解的类,利用反射解析它们,包括解析构造器,方法,属性等等,然后封装成各种信息类放到一个map里。每当你需要一个bean的时候,框架就会从container找是不是有这个类的定义啊?如果找到则通过构造器new出来(这就是控制反转,不用你new,框架帮你new),再在这个类找是不是有要注入的属性或者方法,比如标有@autowired的属性,如果有则还是到container找对应的解析类,new出对象,并通过之前解析出来的信息类找到setter方法,然后用该方法注入对象(这就是依赖注入)。如果其中有一个类container里没找到,则抛出异常,比如常见的spring无法找到该类定义,无法wire的异常。还有就是嵌套bean则用了一下递归,container会放到servletcontext里面,每次reQuest从servletcontext找这个container即可,不用多次解析类定义。如果bean的scope是singleton,则会重用这个bean不再重新创建,将这个bean放到一个map里,每次用都先从这个map里面找。如果scope是session,则该bean会放到session里面。仅此而已,没必要花更多精力。建议还是多看看底层的知识。

原文地址:https://www.cnblogs.com/myseries/p/10752763.html

时间: 2024-11-08 19:14:13

关于spring的源码的理解的相关文章

看看Spring的源码——Bean加载过程

最近几天跟同事聊起Spring的一些问题,对一些地方有些疑问,趁这两天有点空,看看Spring的源码,了解下具体的实现细节.本文基于Spring 4.0.5版本. 首先Web项目使用Spring是通过在web.xml里面配置org.springframework.web.context.ContextLoaderListener初始化IOC容器的. <listener> <listener-class>org.springframework.web.context.ContextL

Spring:源码解读Spring IOC原理

Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. IoC容器的初始化 1. XmlBeanFactory(屌丝IOC)的整个流程 2. FileSystemXmlApplicationContext 的IOC容器流程 1.高富帅IOC解剖 2. 设置资源加载器和资源定位 3.AbstractApplicationContext的refresh函数载入

Spring IoC源码解析——Bean的创建和初始化

Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,MyBatis框架等组合使用. IoC介绍 IoC是什么 Ioc-Inversion of Control,即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控

spring mvc源码解析

1.从DispatcherServlet开始     与很多使用广泛的MVC框架一样,SpringMVC使用的是FrontController模式,所有的设计都围绕DispatcherServlet 为中心来展开的.见下图,所有请求从DispatcherServlet进入,DispatcherServlet根据配置好的映射策略确定处理的 Controller,Controller处理完成返回ModelAndView,DispatcherServlet根据配置好的视图策略确定处理的 View,由V

Spring IOC源码详解之容器依赖注入

Spring IOC源码详解之容器依赖注入 上一篇博客中介绍了IOC容器的初始化,通过源码分析大致了解了IOC容器初始化的一些知识,先简单回顾下上篇的内容 载入bean定义文件的过程,这个过程是通过BeanDefinitionReader来完成的,其中通过 loadBeanDefinition()来对定义文件进行解析和根据Spring定义的bean规则进行处理 - 事实上和Spring定义的bean规则相关的处理是在BeanDefinitionParserDelegate中完成的,完成这个处理需

spring bean源码简单解析

最近在看spring的源码,发现看这个还是有点早,看的很吃力,有多东西还不是很明白,像代理等, 我感觉spring用abstract模板来写主要功能,用接口来拓展功能,用的出神入化,但也让很多简单 的东西变得不那么好懂了,就是写的啰嗦了,个人感觉.下面就是下spring bean源码的学习: private static final Resource RETURNS_NULL_CONTEXT = qualifiedResource(CLASS, "returnsNull.xml");

Spring:源码解读Spring IOC原理--(转载)

转自:http://www.cnblogs.com/ITtangtang/p/3978349.html 这篇文章个人觉得整理的很不错,很值得学习,为了方便自己学习和大家学习,特转载此文保留.请尊重原创~~ Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. IoC容器的初始化 1. XmlBeanFactory(屌丝IOC)的整个流程 2. FileS

SSH 之 Spring的源码(一)——Bean加载过程

看看Spring的源码,看看巨人的底层实现,拓展思路,为了更好的理解原理,看看源码,深入浅出吧.本文基于Spring 4.0.8版本. 首先Web项目使用Spring是通过在web.xml里面配置 org.springframework.web.context.ContextLoaderListener初始化IOC容器的 <span style="font-family:SimSun;font-size:18px;"><listener> <listene

Spring AOP源码解析——专治你不会看源码的坏毛病!

昨天有个大牛说我啰嗦,眼光比较细碎,看不到重点.太他爷爷的有道理了!要说看人品,还是女孩子强一些. 原来记得看到一个男孩子的抱怨,说怎么两人刚刚开始在一起,女孩子在心里就已经和他过完了一辈子.哥哥们,不想这么远行吗?看看何洁,看看带着俩娃跳楼的妈妈. 所以现在的女孩子是很明白的,有些男孩子个子不高,其貌不扬,但是一看那人品气质就知道能找个不错的女盆友.不过要说看人的技术能力,男孩子确实更胜一筹,咱得努力了. 总结一下要形成的习惯: 有空时隔一段时间要做几道算法题,C语言和JAVA都可以,主要是训