Spring IoC容器实现原理

【Spring依赖注入原理】
http://zxf-noimp.iteye.com/blog/1050202
—————————————————————————————————————————
 
【BeanFactory工厂模式】
 
BeanFactory 有三个子类:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。
XmlBeanFactory就是针对最基本的ioc容器的实现。
 
ApplicationContext接口的实现,我们看出其特点:
1.  支持信息源,可以实现国际化。(实现MessageSource接口)
2.  访问资源。(实现ResourcePatternResolver接口,这个后面要讲)
3.  支持应用事件。(实现ApplicationEventPublisher接口)
 
—————————————————————————————————————————
 
【BeanDefinition】
Bean 的解析主要就是对 Spring 配置文件的解析。
 
—————————————————————————————————————————
【IoC容器的初始化】
IoC容器的初始化包括BeanDefinition的Resource定位、载入和注册这三个基本过程。
 
AbstractApplicationContext的refresh函数载入Bean定义。
loadBeanDefinitions方法,容器真正调用的是其子类AbstractXmlApplicationContext对该方法的实现。
 
AbstractBeanDefinitionReader的loadBeanDefinitions方法。
XmlBeanDefinitionReader加载Bean定义资源。
 
BeanDefinitionDocumentReader接口通过registerBeanDefinitions方法调用其实现类DefaultBeanDefinitionDocumentReader对Document对象进行解析。
 
注册:this.beanDefinitionMap.put(beanName, beanDefinition);  
 
—————————————————————————————————————————
 
【IOC容器的依赖注入】
 
用户第一次通过getBean方法向IoC容索要Bean时,IoC容器触发依赖注入。
 
(1).createBeanInstance:生成Bean所包含的java对象实例。
 
(2).populateBean :对Bean属性的依赖注入进行处理。
 
—————————————————————————————————————————
实例化
 
在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。
 
依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。
 
—————————————————————————————————————————
IoC容器工作原理
 
大致分为BeanDefinition的定位、IoC容器初始化、依赖注入三个过程,具体说明如下:
 
BeanDefinition的定位。对IoC容器来说,它为管理POJO之间的依赖关系提供了帮助,但也要依据Spring的定义规则提供bean定义信息。我们可以使用各种形式的bean定义信息,其中比较常用的是以XML的形式定义。在bean定义方面,Spring为用户提供了很大的灵活性。在初始化IoC容器的过程中,首先要定位到这些有效的Bean定义信息,Spring使用Resource来统一Bean定义信息,而定位有ResourceLoader完成。如果使用上下文,ApplicationContext为用户提供了定位的功能。因为上下文本身就是DefaultResourceLoader的子类,IoC容器接口的设计图下图所示。如果使用基本的BeanFactory作为IoC容器,客户需要手工为BeanFactory指定相应的Resource来定位Bean信息。
 
IoC容器的初始化。在使用上下文时,需要先对它进行初始化,完成初始化后,才能对IoC进行使用。初始化的入口就是refresh()函数,它相当于容器的初始化函数。
        在初始化过程中,比较重要的部分是对BeanDefinition信息的载入和注册工作。
        相当于在IoC容器中建立一个BeanDefinition定义的数据映像,Spring为了达到载入的灵活性,把载入的功能从IoC容器中分离出来,由BeanDefinitionReader来完成Bean定义信息的读取、解析和IoC容器内部BeanDefinition的建立。
        在DefaultListableBeanFactory中,这些BeanDefinition被维护在一个HashMap中,以后的IoC容器对Bean的管理和操作都是通过这些BeanDefinition来完成的。
 
 
依赖注入。在容器初始化完成后,IoC容器的使用就准备好了,但这只是在IoC容器内部建立了BeanDefinition,具体的依赖关系还没有注入,用户在第一次向IoC容器请求bean时,IoC容器对相关的bean依赖关系进行注入。
        如果需要提前注入,用户可通过lazy-init属性进行预实例化,这个预实例化是上下文初始化的一部分,起到提前完成依赖关系注入的控制作用,在依赖注入完成后,IoC容器就会保持这些具备依赖关系的bean直接供用户使用,这时,可通过getBean来获取具体的bean实例,这些bean不是简单的java对象,而是包含了对象之间依赖关系的bean,尽管这些依赖注入对于用户来说都是透明的。
        通过BeanDefinitionResolver来对BeanDefinition解析。然后注入到property中。
 
—————————————————————————————————————————
 
依赖对象的获得被反转。把注入交给IoC容器。简化对象依赖关系管理。
 
P21 接口关系图
BeanFactory ->  HierarchicalBeanFactory -> ConfigurableBeanFactory
BeanFactory -> ListableBeanFactory -> ApplicationContext
BeanFactory -> AutowireCapableBeanFactory -> ApplicationContext(MessageSource, ResourceLoader, ApplicationEventPublisher)
 
【BeanFactory】最基本的IoC容器的功能 P24
getBean(), containsBean(), isSingleton()
 
【XmlBeanFactory设计原理】
XmlBeanFactory -> DefaultListableBeanFactory
XmlBeanDefinitionReader处理XML信息。Resource类封装I/O操作。reader.loadBeanDefinitions(resource);
 
通过持有或扩展DefaultListableBeanFactory来获得基本的IoC功能。【编程式使用IoC容器】
ClassPathResource res = new ClassPathResource("bean.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory ();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);
 
【ApplicationContext 在BeanFactory 上添加的】
MessageSource支持多种信息源
ResourceLoader 访问Resource
支持应用事件(Bean的管理) ApplicationEventPublisher
 
【ApplicationContext 设计原理】
FileSystemXmlApplicationContext,基类:AbstractXmlApplicationContext
【FileSystemXmlApplicationContext - ClassPathXmlApplicationContext - XmlWebApplicationContext】
 
—————————————————————————————————————————
IoC容器初始化过程
 
正式启动:refresh()。BeanDefinition:
1.Resource定位。P36 FileSystemResource,ClassPathResource
2.BeanDefinition载入。POJO bean在IoC容器中的抽象。
3.注册BeanDefinition。注册到HashMap。
bean定义载入不是依赖注入。依赖注入在第一次getBean()的时候才会发生。
 
【BeanDefinition的Resource定位】
AbstractApplicationContext的基类是DefaultResourceLoader
refreshBeanFactory:createBeanFactory ->(DefaultListableBeanFactory)
loadBeanDeifinitions
resourceLoader.getResources(location);
 
【BeanDefinition载入和解析】操作BeanDefinition(HashMap)
P38:refresh方法(ApplicationContext初始化)在AbstractApplicationContext类中。
        完成载入:启动读取器(beanDefinitionReader)
P43:解析:DocumentReader。具体解析方法:parseArrayElement(类BeanDefinitionParseDelegate)
 
【BeanDefinition注册】beanDefinitionMap
—————————————————————————————————————————
【依赖注入的实现】createBean():AbstractAutowireCapableBeanFacotry.
        实例化:反射orCGLIB。递归完成依赖注入。
 
—————————————————————————————————————————
《Spring IOC容器基本原理》
http://www.cnblogs.com/linjiqin/archive/2013/11/04/3407126.html
 
 
—————————————————————————————————————————
反射编程
       根据给出的类名(字符串方式)来动态地生成对象。这种编程方式可以让对象在生成时才决定到底是哪一种对象
       我们可以把IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义。
       然后利用编程语言的的反射编程,根据配置文件中给出的类名生成相应的对象。
       从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。
—————————————————————————————————————————
 
 


posted @ 2015-09-18 20:20  Uncle_Nucky  阅读(850)  评论(0编辑  收藏  举报