zoukankan      html  css  js  c++  java
  • IOC原理

    http://www.cnblogs.com/ITtangtang/p/3978349.html

    Spring的bean的创建是典型的工厂模式,BeanFactory定义了IOC容器的基本功能规范。而bean对象是具体如何产生的要看具体的IOC容器实现。

    常用的IOC容器实现方式有四种,XmlBeanFactory就是针对最基本的IOC容器的实现(无法使用注解进行注入)。可以读取XML文件中的BeanDefination(xml中对bean的描述。)

    IOC容器的初始化包括Bean资源文件定位,载入bean资源文件并注册beanDefination这两个基本的过程。 

    ApplicationContext ctx = new ClassPathXmlApplicationContext("config/spring/beans.xml");做了些什么?

    1.层层调用父类构造函数设置bean资源加载器

    2.设置bean定义资源文件(配置文件)的路径

    3.执行refresh()函数对bean定义资源文件进行载入:IOC容器里面维护了一个单例的BeanFactory,如果bean的配置有修改,也可以直接调用refresh方法,它将销毁之前的BeanFactory,重新创建一个BeanFactory。所以叫refresh也是能理解的。    

    refresh()函数核心步骤:1.将xml配置文件转换成resource对象

                                           2、将Resource里定义的bean转换成同意的BeanDefination

                                           3.将BeanDefination注册到BeanFactory,完成BeanFactory的初始化。(BeanFactory中会维护一个BeanDefination的MAP)

     之后getBean的时候就会从BeanFactory中根据bean的beanDefination去实例化一个bean。

                                                                       

    从getBean开始

     http://blog.csdn.net/lisongjia123/article/details/52134396

    http://blog.csdn.net/zghwaicsdn/article/details/50910384

    一:doGetBean方法;

    1.判断beanName是否为空,为空抛出异常提示name不能为空,否则判断beanName是否以&开头,是的话去掉&。

    2.执行getSingleton(beanName);获取bean的登记式单例模式的单例,如果需要的单例不为空的话返回已存在的单例,返回语句在方法结尾处。

    if ((sharedInstance != null) && (args == null)) {
    if (this.logger.isDebugEnabled()) {
    if (isSingletonCurrentlyInCreation(beanName)) {
    this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
    }
    else{
    this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
    }
    }
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    3.如果beanDefination中不存在指定bean的beanDefination并且父级容器不为空则去父级容器中请求bean

    if ((parentBeanFactory != null) && (!containsBeanDefinition(beanName)))
    {
    String nameToLookup = originalBeanName(name);
    if (args != null)
    {
    return parentBeanFactory.getBean(nameToLookup, args);
    }

    return parentBeanFactory.getBean(nameToLookup, requiredType);
    }

    4.获取beanDefination中当前请求bean所依赖的所有bean名称,不为空的话去递归调用getBean方法

    String[] dependsOn = mbd.getDependsOn();
    if (dependsOn != null) {
    for (int i = 0; i < dependsOn.length; i++) {
    String dependsOnBean = dependsOn[i];
    getBean(dependsOnBean);
    registerDependentBean(dependsOnBean, beanName);
    }

    }

    5.如果是单例模式创建单例模式的bean,如果是原型模式创建原型模式的bean(用户每次请求bean会创建一个新的实例),否则根据bean定义资源中配置的生命周期范围实例化bean。

     web应用程序中比较常用,比如request,session,application等生命周期。

    if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, new ObjectFactory() {
    public Object getObject() throws BeansException {
    try {
    return AbstractBeanFactory.this.createBean(beanName, mbd, args);
    }
    catch (BeansException ex)
    {
    AbstractBeanFactory.this.destroySingleton(beanName);
    throw ex;}
    }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }


    else if (mbd.isPrototype())
    {
    Object prototypeInstance = null;
    try {
    beforePrototypeCreation(beanName);
    prototypeInstance = createBean(beanName, mbd, args);
    }
    finally {
    afterPrototypeCreation(beanName);
    }
    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    }

    else
    {
    String scopeName = mbd.getScope();
    Scope scope = (Scope)this.scopes.get(scopeName);
    if (scope == null)
    throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
    try
    {
    Object scopedInstance = scope.get(beanName, new ObjectFactory() {
    public Object getObject() throws BeansException {
    AbstractBeanFactory.this.beforePrototypeCreation(beanName);
    try {
    return AbstractBeanFactory.this.createBean(beanName, mbd, args);
    }
    finally {
    AbstractBeanFactory.this.afterPrototypeCreation(beanName);
    }
    }
    });
    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);

    二:doCreateBean方法(AbstractAutowireCapableBeanFactory)

    二.1用beanName和beanDefination为参数创建实例对象

    instanceWrapper = createBeanInstance(beanName, mbd, args);

          三种方式实例化:

    1.如果rootBeanDefination的工厂方法名不为空,用工厂方法模式创建实例。

    if (mbd.getFactoryMethodName() != null)  {

    2.如果方法传进来的参数args不为空使用自动装配方式实例化,容器的自动装配是根据参数类型匹配bean的构造方法。

     要想不为空,从getBean开始就得传

    3.使用默认的无参构造方法实例化bean

    此方式最常用:beandefination判断MethodOverrides()类中hashset集合性质的一个属性中维护的MethodOverride类是否为空,为空的话用反射机制来实例化,否则用CGLIB动态代理技术来进行实例化。

     

    二.2.bean对象的初始化,依赖注入在此触发。 exposedObject 在初始化完成后返回作为依赖注入完成后的bean

    Object exposedObject = bean;
    try {

    将bean实例对象封装,并且将bean定义中配置的属性值赋值实例对象
    populateBean(beanName, mbd, instanceWrapper);

    初始化bean对象
    exposedObject = initializeBean(beanName, exposedObject, mbd);
    }

    http://www.cnblogs.com/davidwang456/p/4192318.html (BeanDefination是接口)

    populateBean()方法:填充bean

    1.获取容器解析bean定义资源时给beanDefination设置的属性值

    PropertyValues pvs = mbd.getPropertyValues();

    2.设置属性前先调用后置处理器

    http://www.cnblogs.com/sishang/p/6576665.html(后置处理器:如果要在bean实例化、初始化前后加一些自己的逻辑处理,需要定义一个或多个BeanPostProcessor的实现类来,然后注册到IOC容器中。)

    3.首先处理autoaire自动装配的注入

    使用取得的当前Bean的属性名作为Bean的名字,向IoC容器getBean ,然后把从容器得到的Bean设置(setPropertyValues)到当前Bean的属性中去

    4.解析

    判断属性值是否需要解析,比如属性值为另一个bean的引用,需要先解析再注入

    5.注入:依赖注入的过程就是将bean对象实例设置到它依赖的bean对象属性上去。



     
    新生的小心情
  • 相关阅读:
    数据结构之树和二叉树的一些基本概念
    面向对象的三大特点
    WOJ 1020
    C++ STL copy函数效率分析
    局部特化和类模板成员特化
    局部特化 & 特化
    back_inserter 与 iterator
    new期间的异常
    数组分配
    placement new和delete
  • 原文地址:https://www.cnblogs.com/jianmianruxin/p/7573272.html
Copyright © 2011-2022 走看看