欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈Spring IoC容器的依赖注入原理

程序员文章站 2022-06-30 23:43:44
本文介绍了浅谈spring ioc容器的依赖注入原理,分享给大家,具体如下: ioc容器初始化的过程,主要完成的工作是在ioc容器中建立 beandefinition 数...

本文介绍了浅谈spring ioc容器的依赖注入原理,分享给大家,具体如下:

ioc容器初始化的过程,主要完成的工作是在ioc容器中建立 beandefinition 数据映射,并没有看到ioc容器对bean依赖关系进行注入,

假设当前ioc容器已经载入用户定义的bean信息,依赖注入主要发生在两个阶段

正常情况下,由用户第一次向ioc容器索要bean时触发

但我们可以在 beandefinition 信息中通过控制 lazy-init 属性来让容器完成对bean的预实例化,即在初始化的过程中就完成某些bean的依赖注入的过程

1.getbean触发的依赖注入

在基本的ioc容器接口 beanfactory 中,有一个 getbean 的接口定义,这个接口的实现就是触发依赖注入发生的地方.为了进一步了解这个依赖注入的过程,我们从 defaultlistablebeanfactory 的基类 abstractbeanfactory 入手去看看getbean的实现

// 这里是对 beanfactory 接口的实现,比如getbean接口方法
  //这些getbean接口方法最终是通过调用dogetbean来实现的
  @override
  public object getbean(string name) throws beansexception {
    return dogetbean(name, null, null, false);
  }

  @override
  public <t> t getbean(string name, class<t> requiredtype) throws beansexception {
    return dogetbean(name, requiredtype, null, false);
  }

  @override
  public object getbean(string name, object... args) throws beansexception {
    return dogetbean(name, null, args, false);
  }

  public <t> t getbean(string name, class<t> requiredtype, object... args) throws beansexception {
    return dogetbean(name, requiredtype, args, false);
  }

    //这里是实际取得bean的地方,也就是触发依赖注入发生的地方
  @suppresswarnings("unchecked")
  protected <t> t dogetbean(
      final string name, final class<t> requiredtype, final object[] args, boolean typecheckonly)
      throws beansexception {

    final string beanname = transformedbeanname(name);
    object bean;

    // eagerly check singleton cache for manually registered singletons.
        //急切地检查单例人士缓存手动注册的单例
        //先从缓存中取得bean,处理那些已经被创建过的单例bean,这种bean不要重复创建
    object sharedinstance = getsingleton(beanname);
    if (sharedinstance != null && args == null) {
      if (logger.isdebugenabled()) {
        if (issingletoncurrentlyincreation(beanname)) {
          logger.debug("returning eagerly cached instance of singleton bean '" + beanname +
              "' that is not fully initialized yet - a consequence of a circular reference");
        }
        else {
          logger.debug("returning cached instance of singleton bean '" + beanname + "'");
        }
      }
            //这里的getobjectforbeaninstance完成的是factorybean的相关处理,以取得factorybean的相关处理,以取得factorybean的生产结果,beanfactory和factorybean的区别已在前面讲过,这个过程在后面还会详细地分析
      bean = getobjectforbeaninstance(sharedinstance, name, beanname, null);
    }

    else {
      // fail if we're already creating this bean instance:
      // we're assumably within a circular reference.
      if (isprototypecurrentlyincreation(beanname)) {
        throw new beancurrentlyincreationexception(beanname);
      }

            // // 检查ioc容器中的beandefinition是否存在,若在当前工厂不存在则去顺着双亲beanfactory链一直向上找
      beanfactory parentbeanfactory = getparentbeanfactory();
      if (parentbeanfactory != null && !containsbeandefinition(beanname)) {
        // not found -> check parent.
        string nametolookup = originalbeanname(name);
        if (args != null) {
          // delegation to parent with explicit args.
          return (t) parentbeanfactory.getbean(nametolookup, args);
        }
        else {
          // no args -> delegate to standard getbean method.
          return parentbeanfactory.getbean(nametolookup, requiredtype);
        }
      }

      if (!typecheckonly) {
        markbeanascreated(beanname);
      }

      try {
                //根据bean的名字取得beandefinition 
        final rootbeandefinition mbd = getmergedlocalbeandefinition(beanname);
        checkmergedbeandefinition(mbd, beanname, args);

        // guarantee initialization of beans that the current bean depends on.
                //递归获得当前bean依赖的所有bean(如果有的话)
        string[] dependson = mbd.getdependson();
        if (dependson != null) {
          for (string dep : dependson) {
            if (isdependent(beanname, dep)) {
              throw new beancreationexception(mbd.getresourcedescription(), beanname,
                  "circular depends-on relationship between '" + beanname + "' and '" + dep + "'");
            }
            registerdependentbean(dep, beanname);
            getbean(dep);
          }
        }

                //通过调用createbean方法创建singleton bean实例
        if (mbd.issingleton()) {
          sharedinstance = getsingleton(beanname, new objectfactory<object>() {
            @override
            public object getobject() throws beansexception {
              try {
                return createbean(beanname, mbd, args);
              }
              catch (beansexception ex) {
                // explicitly remove instance from singleton cache: it might have been put there
                // eagerly by the creation process, to allow for circular reference resolution.
                // also remove any beans that received a temporary reference to the bean.
                destroysingleton(beanname);
                throw ex;
              }
            }
          });
          bean = getobjectforbeaninstance(sharedinstance, name, beanname, mbd);
        }
                //这里是创建prototype bean的地方
        else if (mbd.isprototype()) {
          // it's a prototype -> create a new instance.
          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();
          final scope scope = this.scopes.get(scopename);
          if (scope == null) {
            throw new illegalstateexception("no scope registered for scope name '" + scopename + "'");
          }
          try {
            object scopedinstance = scope.get(beanname, new objectfactory<object>() {
              @override
              public object getobject() throws beansexception {
                beforeprototypecreation(beanname);
                try {
                  return createbean(beanname, mbd, args);
                }
                finally {
                  afterprototypecreation(beanname);
                }
              }
            });
            bean = getobjectforbeaninstance(scopedinstance, name, beanname, mbd);
          }
          catch (illegalstateexception ex) {
            throw new beancreationexception(beanname,
                "scope '" + scopename + "' is not active for the current thread; consider " +
                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                ex);
          }
        }
      }
      catch (beansexception ex) {
        cleanupafterbeancreationfailure(beanname);
        throw ex;
      }
    }

    // check if required type matches the type of the actual bean instance.
        // 这里对创建的bean进行类型检查,如果没有问题,就返回这个新创建的bean,这个bean已经是包含了依赖关系的bean
    if (requiredtype != null && bean != null && !requiredtype.isassignablefrom(bean.getclass())) {
      try {
        return gettypeconverter().convertifnecessary(bean, requiredtype);
      }
      catch (typemismatchexception ex) {
        if (logger.isdebugenabled()) {
          logger.debug("failed to convert bean '" + name + "' to required type '" +
              classutils.getqualifiedname(requiredtype) + "'", ex);
        }
        throw new beannotofrequiredtypeexception(name, requiredtype, bean.getclass());
      }
    }
    return (t) bean;
  }

依赖注入就是在这里被触发的.而依赖注入的发生是在容器中的beandefinition数据已经建立好的前提下进行的.虽然我们可以用最简单的方式来描述ioc容器,那就是视其为一个hashmap,但只能说这个hashmap是容器的最基本的数据结构,而不是ioc容器的全部.

关于这个依赖注入过程会在下面详解,图1.1可以看到依赖注入的大致过程.

浅谈Spring IoC容器的依赖注入原理

图1.1 依赖注入的过程

getbean是依赖注入的起点,之后会调用abstractautowirecapablebeanfactory中的createbean来生产需要的bean,还对bean初始化进行了处理,比如实现了在beandefinition中的init-method属性定义,bean后置处理器等.下面通过createbean代码了解这个过程

@override
  protected object createbean(string beanname, rootbeandefinition mbd, object[] args) throws beancreationexception {
    if (logger.isdebugenabled()) {
      logger.debug("creating instance of bean '" + beanname + "'");
    }
    rootbeandefinition mbdtouse = mbd;

    // make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved class
    // which cannot be stored in the shared merged bean definition.
        //这里判断需要创建的bean是否可以被实例化,这个类是否可以通过类加载器来载入
    class<?> resolvedclass = resolvebeanclass(mbd, beanname);
    if (resolvedclass != null && !mbd.hasbeanclass() && mbd.getbeanclassname() != null) {
      mbdtouse = new rootbeandefinition(mbd);
      mbdtouse.setbeanclass(resolvedclass);
    }

    // prepare method overrides.
    try {
      mbdtouse.preparemethodoverrides();
    }
    catch (beandefinitionvalidationexception ex) {
      throw new beandefinitionstoreexception(mbdtouse.getresourcedescription(),
          beanname, "validation of method overrides failed", ex);
    }

    try {
      // give beanpostprocessors a chance to return a proxy instead of the target bean instance.
            //如果bean配置了postprocessor,那么这里返回的是一个proxy
      object bean = resolvebeforeinstantiation(beanname, mbdtouse);
      if (bean != null) {
        return bean;
      }
    }
    catch (throwable ex) {
      throw new beancreationexception(mbdtouse.getresourcedescription(), beanname,
          "beanpostprocessor before instantiation of bean failed", ex);
    }

    try {
      object beaninstance = docreatebean(beanname, mbdtouse, args);
      if (logger.isdebugenabled()) {
        logger.debug("finished creating instance of bean '" + beanname + "'");
      }
      return beaninstance;
    }
    catch (beancreationexception ex) {
      // a previously detected exception with proper bean creation context already...
      throw ex;
    }
    catch (implicitlyappearedsingletonexception ex) {
      // an illegalstateexception to be communicated up to defaultsingletonbeanregistry...
      throw ex;
    }
    catch (throwable ex) {
      throw new beancreationexception(
          mbdtouse.getresourcedescription(), beanname, "unexpected exception during bean creation", ex);
    }
  }



  //接着到docreate中去看看bean是怎样生成的
  protected object docreatebean(final string beanname, final rootbeandefinition mbd, final object[] args) {
    // instantiate the bean.
        //用来持有创建出来的bean对象
    beanwrapper instancewrapper = null;
        //如果是单例,则先把缓存中的同名bean清除
    if (mbd.issingleton()) {
      instancewrapper = this.factorybeaninstancecache.remove(beanname);
    }
        //这里是创建bean的地方,由createbeaninstance来完成
    if (instancewrapper == null) {
            //根据指定bean使用对应的策略创建新的实例,如:工厂方法,构造函数自动注入,简单初始化
      instancewrapper = createbeaninstance(beanname, mbd, args);
    }
    final object bean = (instancewrapper != null ? instancewrapper.getwrappedinstance() : null);
    class<?> beantype = (instancewrapper != null ? instancewrapper.getwrappedclass() : null);

    // allow post-processors to modify the merged bean definition.
    synchronized (mbd.postprocessinglock) {
      if (!mbd.postprocessed) {
        applymergedbeandefinitionpostprocessors(mbd, beantype, beanname);
        mbd.postprocessed = true;
      }
    }

    // eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like beanfactoryaware.
        //是否需要提前曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
    boolean earlysingletonexposure = (mbd.issingleton() && this.allowcircularreferences &&
        issingletoncurrentlyincreation(beanname));
    if (earlysingletonexposure) {
      if (logger.isdebugenabled()) {
        logger.debug("eagerly caching bean '" + beanname +
            "' to allow for resolving potential circular references");
      }
            //为避免后期循环依赖,可以在bean初始化完成前将创建实例的objectfactory加入工厂
      addsingletonfactory(beanname, new objectfactory<object>() {
        @override
        public object getobject() throws beansexception {
                    //对bean再次依赖引用,主要应用smartinstantialiationaware beanpostprocessor,
                    //其中我们熟知的aop就是在这里将advice动态织入bean中,若无则直接返回bean,不做任何处理
          return getearlybeanreference(beanname, mbd, bean);
        }
      });
    }

    // initialize the bean instance.
        //这里是对bean的初始化,依赖注入往往在这里发生,这个exposedobject在初始化处理完后悔返回作为依赖注入完成后的bean
    object exposedobject = bean;
    try {
            //对bean进行填充,将各个属性值注入,其中可能存在依赖于其他bean的属性,则会递归初始化依赖bean
      populatebean(beanname, mbd, instancewrapper);
      if (exposedobject != null) {
                //调用初始化方法,比如init-method
        exposedobject = initializebean(beanname, exposedobject, mbd);
      }
    }
    catch (throwable ex) {
      if (ex instanceof beancreationexception && beanname.equals(((beancreationexception) ex).getbeanname())) {
        throw (beancreationexception) ex;
      }
      else {
        throw new beancreationexception(mbd.getresourcedescription(), beanname, "initialization of bean failed", ex);
      }
    }

    if (earlysingletonexposure) {
      object earlysingletonreference = getsingleton(beanname, false);
            // earlysingletonreference 只有在检测到有循环依赖的情况下才会非空
      if (earlysingletonreference != null) {
        if (exposedobject == bean) {
                    //如果exposedobject 没有在初始化方法中被改变,也就是没有被增强
          exposedobject = earlysingletonreference;
        }
        else if (!this.allowrawinjectiondespitewrapping && hasdependentbean(beanname)) {
          string[] dependentbeans = getdependentbeans(beanname);
          set<string> actualdependentbeans = new linkedhashset<string>(dependentbeans.length);
          for (string dependentbean : dependentbeans) {
                        //检测依赖
            if (!removesingletonifcreatedfortypecheckonly(dependentbean)) {
              actualdependentbeans.add(dependentbean);
            }
          }
                    //因为bean创建后其所依赖的bean一定是已经创建的,actualdependentbeans非空则表示当前bean创建后其依赖的bean却没有全部创建完,也就是说存在循环依赖
          if (!actualdependentbeans.isempty()) {
            throw new beancurrentlyincreationexception(beanname,
                "bean with name '" + beanname + "' has been injected into other beans [" +
                stringutils.collectiontocommadelimitedstring(actualdependentbeans) +
                "] in its raw version as part of a circular reference, but has eventually been " +
                "wrapped. this means that said other beans do not use the final version of the " +
                "bean. this is often the result of over-eager type matching - consider using " +
                "'getbeannamesoftype' with the 'alloweagerinit' flag turned off, for example.");
          }
        }
      }
    }
      // register bean as disposable.
    try {
            //根据scope注册bean
      registerdisposablebeanifnecessary(beanname, bean, mbd);
    }
    catch (beandefinitionvalidationexception ex) {
      throw new beancreationexception(mbd.getresourcedescription(), beanname, "invalid destruction signature", ex);
    }

    return exposedobject;
  }

依赖注入其实包括两个主要过程

  1. 生产bea所包含的java对象
  2. bean对象生成之后,把这些bean对象的依赖关系设置好

我们从上可以看到与依赖注入关系特别密切的方法有

createbeaninstance
生成bean包含的java对象

populatebean.
处理对各种bean对象的属性进行处理的过程(即依赖关系处理的过程)

先来看 createbeaninstance源码

/**
   * create a new instance for the specified bean, using an appropriate instantiation strategy:
   * factory method, constructor autowiring, or simple instantiation.
   * @param beanname the name of the bean
   * @param mbd the bean definition for the bean
   * @param args explicit arguments to use for constructor or factory method invocation
   * @return a beanwrapper for the new instance
   */
  protected beanwrapper createbeaninstance(string beanname, rootbeandefinition mbd, object[] args) {
    // make sure bean class is actually resolved at this point.
        // 确认需要创建的bean实例的类可以实例化
    class<?> beanclass = resolvebeanclass(mbd, beanname);

    if (beanclass != null && !modifier.ispublic(beanclass.getmodifiers()) && !mbd.isnonpublicaccessallowed()) {
      throw new beancreationexception(mbd.getresourcedescription(), beanname,
          "bean class isn't public, and non-public access not allowed: " + beanclass.getname());
    }

    supplier<?> instancesupplier = mbd.getinstancesupplier();
    if (instancesupplier != null) {
      return obtainfromsupplier(instancesupplier, beanname);
    }
        //若工厂方法非空,则使用工厂方法策略对bean进行实例化
    if (mbd.getfactorymethodname() != null) {
      return instantiateusingfactorymethod(beanname, mbd, args);
    }

    // shortcut when re-creating the same bean...
    boolean resolved = false;
    boolean autowirenecessary = false;
    if (args == null) {
      synchronized (mbd.constructorargumentlock) {
                //一个类有多个构造函数,每个构造函数都有不同的参数,所以调用前需要先根据参数锁定构造函数或对应的工厂方法
        if (mbd.resolvedconstructororfactorymethod != null) {
          resolved = true;
          autowirenecessary = mbd.constructorargumentsresolved;
        }
      }
    }
        //如果已经解析过则使用解析好的构造函数方法不需要再次锁定
    if (resolved) {
      if (autowirenecessary) {
                //构造函数自动注入
        return autowireconstructor(beanname, mbd, null, null);
      }
      else {
                //使用默认构造函数构造
        return instantiatebean(beanname, mbd);
      }
    }

    // need to determine the constructor...
         // 使用构造函数对bean进行实例化
    constructor<?>[] ctors = determineconstructorsfrombeanpostprocessors(beanclass, beanname);
    if (ctors != null ||
        mbd.getresolvedautowiremode() == rootbeandefinition.autowire_constructor ||
        mbd.hasconstructorargumentvalues() || !objectutils.isempty(args)) {
      return autowireconstructor(beanname, mbd, ctors, args);
    }

    // no special handling: simply use no-arg constructor.
        //使用默认的构造函数对bean进行实例化
    return instantiatebean(beanname, mbd);
  }

  /**
   * instantiate the given bean using its default constructor.
   * @param beanname the name of the bean
   * @param mbd the bean definition for the bean
   * @return a beanwrapper for the new instance
   */
    //最常见的实例化过程instantiatebean
  protected beanwrapper instantiatebean(final string beanname, final rootbeandefinition mbd) {
         //使用默认的实例化策略对bean进行实例化,默认的实例化策略是
    //cglibsubclassinginstantiationstrategy,也就是使用cglib实例化bean 
    try {
      object beaninstance;
      final beanfactory parent = this;
      if (system.getsecuritymanager() != null) {
        beaninstance = accesscontroller.doprivileged(new privilegedaction<object>() {
          @override
          public object run() {
            return getinstantiationstrategy().instantiate(mbd, beanname, parent);
          }
        }, getaccesscontrolcontext());
      }
      else {
        beaninstance = getinstantiationstrategy().instantiate(mbd, beanname, parent);
      }
      beanwrapper bw = new beanwrapperimpl(beaninstance);
      initbeanwrapper(bw);
      return bw;
    }
    catch (throwable ex) {
      throw new beancreationexception(
          mbd.getresourcedescription(), beanname, "instantiation of bean failed", ex);
    }
  }

这里使用了cglib对bean进行实例化.cglib是一个字节码生成器的类库,它提供了一系列的api来提供生成和转换java的字节码的功能.

在spring aop中也使用cglib对java的字节码进行增强.在ioc容器中,要了解怎样使用cglib来生成bean对象,需要看一下simpleinstantiationstrategy类.它是spring用来生成bean对象的默认类,它提供了两种实例化bean对象的方法

  1. 通过beanutils,使用了java的反射功能
  2. 通过cglib来生成
public class simpleinstantiationstrategy implements instantiationstrategy {
@override
  public object instantiate(rootbeandefinition bd, string beanname, beanfactory owner) {
    // don't override the class with cglib if no overrides.
    if (bd.getmethodoverrides().isempty()) {
            //这里取得指定的构造器或者生成对象的工厂方法来对bean进行实例化
      constructor<?> constructortouse;
      synchronized (bd.constructorargumentlock) {
        constructortouse = (constructor<?>) bd.resolvedconstructororfactorymethod;
        if (constructortouse == null) {
          final class<?> clazz = bd.getbeanclass();
          if (clazz.isinterface()) {
            throw new beaninstantiationexception(clazz, "specified class is an interface");
          }
          try {
            if (system.getsecuritymanager() != null) {
              constructortouse = accesscontroller.doprivileged(new privilegedexceptionaction<constructor<?>>() {
                @override
                public constructor<?> run() throws exception {
                  return clazz.getdeclaredconstructor((class[]) null);
                }
              });
            }
            else {
              constructortouse = clazz.getdeclaredconstructor((class[]) null);
            }
            bd.resolvedconstructororfactorymethod = constructortouse;
          }
          catch (throwable ex) {
            throw new beaninstantiationexception(clazz, "no default constructor found", ex);
          }
        }
      }
      //通过beanutils进行实例化,这个beanutils的实例化通过constructor来实例化bean,在beanutils中可以看到具体的调用ctor.newinstance(args)
      return beanutils.instantiateclass(constructortouse);
    }
    else {   
      // 使用cglib来实例化对象
      return instantiatewithmethodinjection(bd, beanname, owner);
    }
  }
}

bean之间依赖关系的处理

依赖关系处理的入口是前面提到的populatebean方法.由于其中涉及的面太多,在这里就不贴代码了.简要介绍一下依赖关系处理的流程:在populatebean方法中,

首先取得在beandefinition中设置的property值,然后开始依赖注入的过程。

首先处理autowire的注入,可以byname或者是bytype,之后对属性进行注入。

接着需要对bean reference进行解析,在对managelist、manageset、managemap等进行解析完之后,就已经为依赖注入准备好了条件,这是真正把bean对象设置到它所依赖的另一个bean属性中去的地方,其中处理的属性是各种各样的。

依赖注入发生在beanwrapper的setpropertyvalues中,具体的完成却是在beanwrapper的子类beanwrapperimpl中实现的,它会完成bean的属性值的注入,其中包括对array的注入、对list等集合类以及对非集合类的域进行注入。

进过一系列的注入,这样就完成了对各种bean属性的依赖注入过程。

在bean的创建和对象依赖注入的过程中,需要依据beandefinition中的信息来递归地完成依赖注入。

从前面的几个递归过程中可以看到,这些递归都是以getbean为入口的。

一个递归是在上下文体系中查找需要的bean和创建bean的递归调用;

另一个递归是在依赖注入时,通过递归调用容器的getbean方法,得到当前bean的依赖bean,同时也触发对依赖bean的创建和注入。

在对bean的属性进行依赖注入时,解析的过程也是一个递归的过程。这样,根据依赖关系,一层层地完成bean的创建和注入,直到最后完成当前bean的创建。有了这个顶层bean的创建和对它属性依赖注入的完成,意味着和当前bean相关的整个依赖链的注入液完成了。

在bean创建和依赖注入完成以后,在ioc容器中建立起一系列依靠依赖关系联系起来的bean,这个bean已经不再是简单的java对象了。该bean系列以及bean之间的依赖关系建立完成之后,通过ioc的相关接口方法,就可以非常方便地供上层应用使用了。

2. lazy-init属性和预实例化

在前面的refresh方法中,我们可以看到调用了finishbeanfactoryinitialization来对配置了lazy-init的bean进行处理。

其实在这个方法中,封装了对lazy-init属性的处理,实际的处理是在defaultlistablebeanfactory这个基本容器的preinstantiatesingleton方法中完成的。该方法对单例bean完成预实例化,这个预实例化的完成巧妙地委托给容器来实现。如果需要预实例化,那么就直接在这里采用getbean去触发依赖注入,与正常依赖注入的触发相比,只有触发的时间和场合不同。在这里,依赖注入发生在容器执行refresh的过程中,即ioc容器初始化的过程中,而不像一般的依赖注入一样发生在ioc容器初始化完成以后,第一次通过getbean想容器索要bean的时候。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。