spring源码解析-IOC原理

首先以一段简单的代码说明下BeanFactory的使用

public class SimpleBeanFactory {

    public static void main(String[] args) {
        Resource resource = new ClassPathResource("applicationContext.xml");
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions(resource);

        UserService1 userService1 = (UserService1)  beanFactory.getBean("userService1");
        userService1.hello();

    }
}

Ioc容器的使用步骤

  1. 创建Ioc配置文件的抽象资源,这个抽象资源包含了BeanDefinition的定义信息。

  2. 创建一个BeanFactory,这里使用了DefaultListableBeanFactory。

  3. 创建一个载入BeanDefinition的读取器,这里使用XmlBeanDefinitionReader来载入XML文件形式的BeanDefinition,通过一个回调配置给BeanFactory。

  4. 从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成。完成整个载入和注册Bean定义之后,需要的Ioc容器就建立起来了。这个时候我们就可以直接使用Ioc容器了。

loadBeanDefinitions加载BeanDefinition

  1. XmlBeanDefinitionReader.loadBeanDefinitions->doLoadBeanDefinitions
  2. XmlBeanDefinitionReader.doLoadDocument ->DefaultDocumentLoader.loadDocument,使用sax解析xml文件

  3. XmlBeanDefinitionReader.registerBeanDefinitions->DefaultBeanDefinitionDocumentReader.registerBeanDefinitions->doRegisterBeanDefinitions 把document解析成BeanDefinition.

  4. DefaultBeanDefinitionDocumentReader.parseBeanDefinitions, parseDefaultElement解析默认的节点,parseCustomElement 解析自定义元素节点 , 并调用BeanDefinitionReaderUtils.registerBeanDefinition把BeanDefinition注册到容器中。
  5. DefaultBeanDefinitionDocumentReader委托BeanDefinitionParserDelegate进行解析,parseBeanDefinitionElement解析并返回BeanDefinitionHolder对象。
  6. DefaultListableBeanFactory.registerBeanDefinition把生成的BeanDefinition对象注册到容器中。

可以看到,真正解析xml是在DefaultDocumentLoader中,组装BeanDefinition是在BeanDefinitionParserDelegate中,注册是在DefaultListableBeanFactory中。

对象的依赖注入

上边只完成了BeanDefinition的加载注册,而对象的初始化与注入则是在调用getBean时进行的。

  1. AbstractBeanFactory.getBean()方法,调用doGetBean.
  2. 如果是单例的,直接从缓存中取.
  3. 从父工厂中取实例
  4. 注册依赖关系,递归调用,首先初始化依赖的bean
  5. 对于单例的实例,getSingleton获取实例,第一次会调用createBean创建。
  6. 原型则直接调用createBean创建
  7. 使用getObjectForBeanInstance处理FactoryBean的返回。

AbstractAutowireCapableBeanFactory.createBean方法 。

  1. 调用resolveBeforeInstantiation对BeanPostProcessor进行回调

  2. doCreateBean创建实例

  3. createBeanInstance创建BeanWrapper,调autowireConstructor或instantiateBean。

  4. 当有复写父类的方法,会用cglib创建实例。

  5. SimpleInstantiationStrategy.instantiate->CglibSubclassingInstantiationStrategy.instantiateWithMethodInjection实际调用cglib进行实例化对象。

AbstractAutowireCapableBeanFactory.populateBean装载依赖的属性

  1. 自动加载注解的属性
  2. 调用applyPropertyValues方法 对属性进行依赖注入
  3. 对于转换过的属性,直接调用 BeanWrapper.setPropertyValues设置属性
  4. 对于没有转换过的属性,调用BeanDefinitionValueResolver.resolveValueIfNecessary对属性进行转换。
    以resolveReference为例,会调用依赖的beanFactory.getBean(refName)方法获取实例,这样形成递归调用,把所有依赖的对象都实例化出来。

ApplicationContext的设计
* 1.支持不同的信息源。扩展了MessageSource接口,这个接口为ApplicationContext提供了很多信息源的扩展功能,比如:国际化的实现为多语言版本的应用提供服务。
* 2.访问资源。这一特性主要体现在ResourcePatternResolver接口上,对Resource和ResourceLoader的支持,这样我们可以从不同地方得到Bean定义资源。
* 这种抽象使用户程序可以灵活地定义Bean定义信息,尤其是从不同的IO途径得到Bean定义信息。这在接口上看不出来,不过一般来说,具体ApplicationContext都是
* 继承了DefaultResourceLoader的子类。因为DefaultResourceLoader是AbstractApplicationContext的基类,关于Resource后面会有更详细的介绍。
* 3.支持应用事件。继承了接口ApplicationEventPublisher,为应用环境引入了事件机制,这些事件和Bean的生命周期的结合为Bean的管理提供了便利。
* 4.附件服务。EnvironmentCapable里的服务让基本的Ioc功能更加丰富。
* 5.ListableBeanFactory和HierarchicalBeanFactory是继承的主要容器。

以ClassPathXmlApplicationContext为例
1. 构造方法 调用setConfigLocations 方法设置配置文件配置。
2. refesh方法初始化窗口,这个是ApplicationContext的核心 。
3. AbstractApplicationContext.obtainFreshBeanFactory中调用refreshBeanFactory方法,在AbstractRefreshableApplicationContext中实现。
4. 创建一个BeanFactory,并调用loadBeanDefinitions装载BeanDefinition
5. reresh方法中,进行工厂的初始化,处理器,监听器的初始化。 生命周期方法的回调等操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值