其实说到Spring的核心,无非指的就是Ioc容器和AOP。
Spring降低了应用的负载和框架的侵入性,依靠的解决方案正是Ioc和AOP的支持。
学习Spring的Ioc和Aop的设计模式可以帮助我们在自己编写代码的时候如何优雅的设计和实现。
这里就只记录一下自己对Ioc容器设计和实现的走读和思考。
在查看Spring Ioc容器的设计文档和源代码后,发现其实只有2类主要的容器:
一类是实现BeanFactory接口,这类的容器只实现了基本的方法,从名字上就大概能知道是什么功能:一类是实现ApplicationContext接口,继承了ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver,包括了Beanfactory定义的所有功能和自己增加了许多面向框架的特性。
基本上这2类涵盖了所有常用到的Ioc容器的方法。
在需要自己定制特定功能的容器的时候,可以参考已经定义好的容器产品,不需要自己再来重新设计了。
具体的继承关系可以通过源代码来查看:可以看到ApplicationContext之所以比beanFactory高级是因为它不仅继承了beanFactory,而且还继承了其它的接口。
1.为了理解beanFactory这一类简单容器的bean的初始化过程,可以看一下它的一个常见的最底层实现XmlBeanFactory:其中AbstractBeanFactory是实现ConfigurableBeanFactory接口的抽象类。
其实看spring的源码,它的命名规范是值得学习的,从每个名字上看都可以大致明白它的功能。
这个是从xml文件中读取bean配置并初始化bean。 看XmlBeanFactory的构造方法: 在构造方法中需要得到Resource对象,然后使用XmlBeanDefinitionReader这个对象的loadBeanDefinitions来进行解析载入的过程。
2.再来看一下更高级一点的ApplicationContext容器的实现,因为它又继承了更多的接口,所有具有更多的特性,比如访问资源的多样性,支持事件等。找到一个简单的底层实现类FileSystemXmlApplicationContext,它是继承了抽象类AbstractXmlApplicationContext,继承关系图如下: 因为是抽象类肯定有一部分的方法它已经实现了,这里只需要完成自己扩展的方法就可以了。
看一下它的构造方法: 操作类似的方法全部在基类中实现,比如refresh();setConfigLocations();refresh中包括资源的解析,校验,和注册会在容器启动的时候执行。
refresh方法里面看到了很多步骤,关键的步骤是它如何获取并刷新beanFactory的,可以看看obtainFreshBeanFactory方法,它调用了一个抽象方法refreshBeanFactory,找到它在AbstractRefreshableApplicationContext的实现: 可以看到先有一个销毁的过程,然后再创建....现在明白它为什么会叫refreshAbleApplicationContext了....
然后又进入loadBeanDefinitions(beanFactory)过程了。 接下来的步骤就和基本的容器实现一样了.... 再来看看loadBeanDefinitions的实现: 发现太长了,这里就不贴了....
跟踪到了registerBeanDefinitions方法:
先对XML进行解析,具体的解析是通过BeanDefinitionParserDelegate类parseBeanDefinitionElement类进行的。再往底层方法查看,解析过程中用到了很多hashmap,set,而且发现在spring的bean配置中用到的功能性标签居然写死在了代码中: 看来spring支持的标签也不会经常变化了。
初始化过程到这里算是完结了,但是后面还有一个比较关键的步骤,就是根据依赖的关系(refresh标签)进行注入,或者是自己通过调用getBean方法来促发依赖注入。 基本上都是通过BeanDefinition结构中的refrence标签去填充bean对象的。
大概的流程基本上分成了3步,找到资源文件(可以通过xml文件或者file路径等),解析资源文件(把获取的资源解析成BeanDefinition对象),注册资源文件(其实就是把BeanDefinition放入到一个final的hashmap中,然后根据依赖关系进行注入),而且这几个过程之间是松耦合的,可以灵活的扩展,定义自己的容器。比如refresh方法是基类中定义的,但是调用的getBeanFactory方法却是抽象的,必须由子类根据自己的特性来实现,这样的设计正符合通过扩展来实现变化的开闭原则,学习了。Ioc容器大概的流程根据自己跳跃的思维过了一遍,发现读起来思路基本上很流畅,注释很详细,也是值得学习的。
还有一些比较细节的地方,有时间再细细研究了。
版权声明:本文为博主原创文章,未经博主允许不得转载。