本文转载自互联网,侵删
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
喜欢的话麻烦点下Star哈
文章将同步到我的个人博客:
本文是微信公众号【Java技术江湖】的《Spring和SpringMVC源码分析》其中一篇,本文部分内容来源于网络,为了把本文主题讲得清晰透彻,也整合了很多我认为不错的技术博客内容,引用其中了一些比较好的博客文章,如有侵权,请联系作者。
该系列博文会告诉你如何从spring基础入手,一步步地学习spring基础和springmvc的框架知识,并上手进行项目实战,spring框架是每一个Java工程师必须要学习和理解的知识点,进一步来说,你还需要掌握spring甚至是springmvc的源码以及实现原理,才能更完整地了解整个spring技术体系,形成自己的知识框架。
后续还会有springboot和springcloud的技术专题,陆续为大家带来,敬请期待。
为了更好地总结和检验你的学习成果,本系列文章也会提供部分知识点对应的面试题以及参考答案。
如果对本系列文章有什么建议,或者是有什么疑问的话,也可以关注公众号【Java技术江湖】联系作者,欢迎你参与本系列博文的创作和修订。
前言
本文大致地介绍了IOC容器的初始化过程,只列出了比较重要的过程和代码,可以从中看出IOC容器执行的大致流程。
接下来的文章会更加深入剖析Bean容器如何解析xml,注册和初始化bean,以及如何获取bean实例等详细的过程。
转自:http://www.importnew.com/19243.html
1. 初始化
大致单步跟了下Spring IOC的初始化过程,整个脉络很庞大,初始化的过程主要就是读取XML资源,并解析,最终注册到Bean Factory中:
在完成初始化的过程后,Bean们就在BeanFactory中蓄势以待地等调用了。下面通过一个具体的例子,来详细地学习一下初始化过程,例如当加载下面一个bean:
1 | <bean id="XiaoWang" class="com.springstudy.talentshow.SuperInstrumentalist"> |
加载时需要读取、解析、注册bean,这个过程具体的调用栈如下所示:
下面对每一步的关键的代码进行详细分析:
准备
保存配置位置,并刷新
在调用ClassPathXmlApplicationContext后,先会将配置位置信息保存到configLocations,供后面解析使用,之后,会调用AbstractApplicationContext
的refresh方法进行刷新:
1 | public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, |
创建载入BeanFactory
1 | protected final void refreshBeanFactory() throws BeansException { |
创建XMLBeanDefinitionReader
1 | protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) |
读取
创建处理每一个resource
1 | public int loadBeanDefinitions(String location, Set<Resource> actualResources) |
处理XML每个元素
1 | protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { |
解析和注册bean
1 | protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { |
本步骤中,通过parseBeanDefinitionElement将XML的元素解析为BeanDefinition,然后存在BeanDefinitionHolder中,然后再利用BeanDefinitionHolder将BeanDefinition注册,实质就是把BeanDefinition的实例put进BeanFactory中,和后面将详细的介绍解析和注册过程。
解析
处理每个Bean的元素
1 | public AbstractBeanDefinition parseBeanDefinitionElement( |
处理属性的值
1 | public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) { |
1.4 注册
1 | public static void registerBeanDefinition( |
注册过程中,最核心的一句就是:this.beanDefinitionMap.put(beanName, beanDefinition),也就是说注册的实质就是以beanName为key,以beanDefinition为value,将其put到HashMap中。
注册
1 | public static void registerBeanDefinition( |
理解了以上两个过程,我们就可以自己实现一个简单的Spring框架了。于是,我根据自己的理解实现了一个简单的IOC框架Simple Spring,有兴趣可以看看。
注册过程中,最核心的一句就是:this.beanDefinitionMap.put(beanName, beanDefinition)
,也就是说注册的实质就是以beanName为key,以beanDefinition为value,将其put到HashMap中。
注入依赖
当完成初始化IOC容器后,如果bean没有设置lazy-init(延迟加载)属性,那么bean的实例就会在初始化IOC完成之后,及时地进行初始化。初始化时会先建立实例,然后根据配置利用反射对实例进行进一步操作,具体流程如下所示:
创建bean的实例
创建bean的实例过程函数调用栈如下所示:
注入bean的属性
注入bean的属性过程函数调用栈如下所示:
在创建bean和注入bean的属性时,都是在doCreateBean函数中进行的,我们重点看下:
1 | protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, |
理解了以上两个过程,我们就可以自己实现一个简单的Spring框架了。于是,我根据自己的理解实现了一个简单的IOC框架Simple Spring,有兴趣可以看看。
微信公众号
个人公众号:程序员黄小斜
微信公众号【程序员黄小斜】新生代青年聚集地,程序员成长充电站。作者黄小斜,职业是阿里程序员,身份是斜杠青年,希望和更多的程序员交朋友,一起进步和成长!这一次,我们一起出发。
关注公众号后回复“2019”领取我这两年整理的学习资料,涵盖自学编程、求职面试、算法刷题、Java技术、计算机基础和考研等8000G资料合集。
技术公众号:Java技术江湖
微信公众号【Java技术江湖】一位阿里 Java 工程师的技术小站,专注于 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!
关注公众号后回复“PDF”即可领取200+页的《Java工程师面试指南》强烈推荐,几乎涵盖所有Java工程师必知必会的知识点。