spring IOC容器实现探讨

    xiaoxiao2024-04-20  6

    spring IOC容器的实现,一开始我被复杂的接口和类所掩埋,看不清整体的思路和设计,踟蹰于代码丛林中,摸不清前进的方向。一开始我就决定只研读以xml文件做配置文件的XmlFactoryBean的具体实现为主要目标,渐渐地有了点感觉,用UML把spring中的bean工厂体系展现出来之后就更清晰了,让你不得不感叹设计的精巧和复杂。本文只是我个人对spring IOC实现的理解,如有错误,请不吝赐教,谢谢。     首先,需要理解的是spring容器中bean的生命周期,《spring in action》中的那张图是最好的解释,结合这张图和源码来解读spring中IOC的实现将非常容易理解。这张图完整展示了spring容器中一个bean从创建到销毁的整个生命周期。     1. 容器寻找Bean的定义信息并且将其实例化。 2.受用依赖注入,Spring按照Bean定义信息配置Bean的所有属性。 3.如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。 4.如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。 5.如果BeanPostProcessor和Bean关联,那么它们的postProcessBeforeInitialzation()方法将被调用。 6.如果Bean指定了init-method方法,它将被调用。 7.最后,如果有BeanPsotProcessor和Bean关联,那么它们的postProcessAfterInitialization()方法将被调用。     到这个时候,Bean已经可以被应用系统使用了,并且将被保留在Bean Factory中知道它不再需要。有两种方法可以把它从Bean Factory中删除掉。 1.如果Bean实现了DisposableBean接口,destory()方法被调用。 2.如果指定了订制的销毁方法,就调用这个方法。         下面我们将会看到,这些bean创建销毁的每个阶段是如何在源码中实现的。     再看看spring中bean工厂的完整体系,比较复杂,不过我们只需要关注其中的几个核心工厂。           (看不清楚,请 下载图片来看,比较清晰)     这些工厂类没有在同一个包内,分布在org.springframework.beans以及它的子包内,把它们放在一起就看的比较清楚了。我们需要关注的是这么两个类:org.springframework.beans.factory.support.AbstractBeanFactory org.springframework.beans.factory.support.DefaultListableBeanFactory 以及接口: org.springframework.beans.factory.support.BeanDefinitionRegistry     AbstractBeanFactory作为BeanFactory接口的抽象实现类,是其他工厂类的父类,提供了bean的singlton缓存、singleton/prototype的决定、bean的别名以及bean和它的子类bean的定义合并(bean definition merging for child bean definitions)和销毁。这里有3个重载的getBean方法(实现BeanFactory定义的getBean方法),我们关注下最主要的这个方法: public  Object getBean(String name, Class requiredType, Object[] args)  throws  BeansException {         String beanName  =  transformedBeanName(name);         Object bean  =   null ;          //  Eagerly check singleton cache for manually registered singletons.         Object sharedInstance  =   null ;          // 从单例缓存中获取          synchronized  ( this .singletonCache) {             sharedInstance  =   this .singletonCache.get(beanName);         }          if  (sharedInstance  !=   null ) {              if  (isSingletonCurrentlyInCreation(beanName)) {                  if  (logger.isDebugEnabled()) {                     logger.debug( " Returning eagerly cached instance of singleton bean ' "   +  beanName  +                              " ' that is not fully initialized yet - a consequence of a circular reference " );                 }             }              else  {                  if  (logger.isDebugEnabled()) {                     logger.debug( " Returning cached instance of singleton bean ' "   +  beanName  +   " ' " );                 }             }             bean  =  getObjectForSharedInstance(name, sharedInstance);         }          else  {              //  Fail if we're already creating this singleton instance:              //  We're assumably within a circular reference.              if  (isSingletonCurrentlyInCreation(beanName)) {                  throw   new  BeanCurrentlyInCreationException(beanName);             }              //  Check if bean definition exists in this factory.              // 检测bean是否定义在父工厂              if  (getParentBeanFactory()  !=   null   &&   ! containsBeanDefinition(beanName)) {                  //  Not found -> check parent.                  if  (getParentBeanFactory()  instanceof  AbstractBeanFactory) {                      //  Delegation to parent with args only possible for AbstractBeanFactory.                      return  ((AbstractBeanFactory) getParentBeanFactory()).getBean(name, requiredType, args);                 }                  else   if  (args  ==   null ) {                      //  No args -> delegate to standard getBean method.                      return  getParentBeanFactory().getBean(name, requiredType);                 }                  else  {                      throw   new  NoSuchBeanDefinitionException(beanName,                              " Cannot delegate to parent BeanFactory because it does not supported passed-in arguments " );                 }             }              // 获取BeanDefinition             RootBeanDefinition mergedBeanDefinition  =  getMergedBeanDefinition(beanName,  false );             checkMergedBeanDefinition(mergedBeanDefinition, beanName, requiredType, args);              //  Create bean instance.              // 创建bean,如果为为singleton              if  (mergedBeanDefinition.isSingleton()) {                  synchronized  ( this .singletonCache) {                      //  Re-check singleton cache within synchronized block.                     sharedInstance  =   this .singletonCache.get(beanName);                      if  (sharedInstance  ==   null ) {                          if  (logger.isDebugEnabled()) {                             logger.debug( " Creating shared instance of singleton bean ' "   +  beanName  +   " ' " );                         }                          this .currentlyInCreation.add(beanName);                          try  {                             sharedInstance  =  createBean(beanName, mergedBeanDefinition, args);                             //加进单例缓存                             addSingleton(beanName, sharedInstance);                         }                          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.                             destroyDisposableBean(beanName);                              throw  ex;                         }                          finally  {                              this .currentlyInCreation.remove(beanName);                         }                     }                 }                 bean  =  getObjectForSharedInstance(name, sharedInstance);             }              // 如果是prototype              else  {                  //  It's a prototype -> create a new instance.                 bean  =  createBean(beanName, mergedBeanDefinition, args);             }         }          //  Check if required type matches the type of the actual bean instance.          if  (requiredType  !=   null   &&   ! requiredType.isAssignableFrom(bean.getClass())) {              throw   new  BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());         }          return  bean;     }     当你调用getBean获取一个bean的时候,spring首先查找单例缓存中是否已经有这个bean,有的话直接返回(首先会判断是否已经创建),如果没有,spring就开始创建这个bean:首先获取bean的定义(BeanDefinition),检测bean是否定义在父工厂中,有的话调用父工厂的getBean方法;没有就检测bean是singleton还是prototype,如果是singleton就是创建bean并加入缓存以便下次直接调用,如果是prototype,就在每次调用时重新创建一个bean实例。注意createBean(beanName, mergedBeanDefinition, args); 这个方法,这是创建bean的核心方法,并且是一个abstract方法,将被子类实现。     看看是如何获取bean的定义的, protected  RootBeanDefinition getMergedBeanDefinition(String name,  boolean  includingAncestors)          throws  BeansException {         String beanName  =  transformedBeanName(name);          //  Efficiently check whether bean definition exists in this factory.          if  (includingAncestors  &&   ! containsBeanDefinition(beanName)  &&                 getParentBeanFactory()  instanceof  AbstractBeanFactory) {              return  ((AbstractBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName,  true );         }          //  Resolve merged bean definition locally.          return  getMergedBeanDefinition(beanName, getBeanDefinition(beanName));     }     调用重载的getMergedBeanDefinition合并父工厂和子工厂中的bean定义,注意getBeanDefinition(beanName),这是一个抽象方法,延迟到子类实现以便提供获取bean定义的具体方法,这个方法和 createBean 一样都是template method模式的应用。看看它们的定义: protected   abstract  BeanDefinition getBeanDefinition(String beanName)  throws  BeansException; protected   abstract  Object createBean(             String beanName, RootBeanDefinition mergedBeanDefinition, Object[] args)  throws  BeanCreationException;       基本了解了AbstractBeanFactory 后,我们来看看它的子类的AbstractAutowireCapableBeanFactory ,这个类实现了createBean() ,在这个方法中我们将看到与 上面bean的生命周期图对应的 bean的创建过程,英文注释已经非常清楚: protected  Object createBean(String beanName, RootBeanDefinition mergedBeanDefinition, Object[] args)              throws  BeanCreationException {          if  (logger.isDebugEnabled()) {             logger.debug( " Creating instance of bean ' "   +  beanName  +                      " ' with merged definition [ "   +  mergedBeanDefinition  +   " ] " );         }         Object bean  =   null ;          //  Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.          if  (mergedBeanDefinition.hasBeanClass()) {             bean  =  applyBeanPostProcessorsBeforeInstantiation(mergedBeanDefinition.getBeanClass(), beanName);              if  (bean  !=   null ) {                  return  bean;             }         }          //  Guarantee initialization of beans that the current one depends on.          if  (mergedBeanDefinition.getDependsOn()  !=   null ) {              for  ( int  i  =   0 ; i  <  mergedBeanDefinition.getDependsOn().length; i ++ ) {                 getBean(mergedBeanDefinition.getDependsOn()[i]);             }         }         BeanWrapper instanceWrapper  =   null ;         Object originalBean  =   null ;         String errorMessage  =   null ;          try  {              //  Instantiate the bean.             errorMessage  =   " Instantiation of bean failed " ;              if  (mergedBeanDefinition.getFactoryMethodName()  !=   null )  {                 instanceWrapper  =  instantiateUsingFactoryMethod(beanName, mergedBeanDefinition, args);             }              else   if  (mergedBeanDefinition.getResolvedAutowireMode()  ==  RootBeanDefinition.AUTOWIRE_CONSTRUCTOR  ||                     mergedBeanDefinition.hasConstructorArgumentValues() )  {                 instanceWrapper  =  autowireConstructor(beanName, mergedBeanDefinition);             }              else  {                  //  No special handling: simply use no-arg constructor.                 instanceWrapper  =  instantiateBean(beanName, mergedBeanDefinition);             }             bean  =  instanceWrapper.getWrappedInstance();              //  Eagerly cache singletons to be able to resolve circular references              //  even when triggered by lifecycle interfaces like BeanFactoryAware.              if  (isAllowCircularReferences()  &&  isSingletonCurrentlyInCreation(beanName)) {                  if  (logger.isDebugEnabled()) {                     logger.debug( " Eagerly caching bean with name ' "   +  beanName  +                              " ' to allow for resolving potential circular references " );                 }                 addSingleton(beanName, bean);             }              //  Initialize the bean instance.             errorMessage  =   " Initialization of bean failed " ;             populateBean(beanName, mergedBeanDefinition, instanceWrapper);              if  (bean  instanceof  BeanNameAware) {                  if  (logger.isDebugEnabled()) {                     logger.debug( " Invoking setBeanName on BeanNameAware bean ' "   +  beanName  +   " ' " );                 }                 ((BeanNameAware) bean).setBeanName(beanName);             }              if  (bean  instanceof  BeanFactoryAware) {                  if  (logger.isDebugEnabled()) {                     logger.debug( " Invoking setBeanFactory on BeanFactoryAware bean ' "   +  beanName  +   " ' " );                 }                 ((BeanFactoryAware) bean).setBeanFactory( this );             }             originalBean  =  bean;             bean  =  applyBeanPostProcessorsBeforeInitialization(bean, beanName);             invokeInitMethods(beanName, bean, mergedBeanDefinition);             bean  =  applyBeanPostProcessorsAfterInitialization(bean, beanName);         }          catch  (BeanCreationException ex) {              throw  ex;         }          catch  (Throwable ex) {              throw   new  BeanCreationException(                     mergedBeanDefinition.getResourceDescription(), beanName, errorMessage, ex);         }          //  Register bean as disposable, and also as dependent on specified "dependsOn" beans.         registerDisposableBeanIfNecessary(beanName, originalBean, mergedBeanDefinition);          return  bean;     }     通过instanceof操作符来判断bean是否实现了用于生命周期回调的接口,然后调用相应的回调方法,可以看到spring充分实践了针对接口编程的原则,虽然很夸张的一个方法一个接口的地步,不过这些接口也是作为mark interface用于标记回调。结合上面的生命周期图看这段代码将很好理解。有了bean的创建方法,那么如何获取bean在配置文件中的定义信息呢?也就是在哪里实现了 getBeanDefinition方法呢?答案就在AbstractAutowireCapableBeanFactory 的子类DefaultListableBeanFactory中。     DefaultListableBeanFactory 不仅继承了AbstractAutowireCapableBeanFactory ,还实现了BeanDefinitionRegistry和ConfigurableListableBeanFactory接口。其中ConfigurableListableBeanFactory接口是定义了分析和修改bean定义信息的回调方法,暂时不去管它。看看BeanDefinitionRegistry接口: public   interface  BeanDefinitionRegistry {    int  getBeanDefinitionCount();   String[] getBeanDefinitionNames();   BeanDefinition getBeanDefinition(String beanName)  throws  NoSuchBeanDefinitionException;   String[] getAliases(String beanName)  throws  NoSuchBeanDefinitionException;    void  registerAlias(String beanName, String alias)  throws  BeansException;    void  registerBeanDefinition(String beanName, BeanDefinition beanDefinition)              throws  BeansException;   ...... } 一系列用于获取bean定义信息的方法,这个接口我们将在后面的代码中看到,作为一个mark inteface。注意咯,这个接口中非常关键的一个方法就是registerBeanDefinition,这个方法用于向bean工厂注册解析的每个bean定义,我们将在xml文件的解析的环节看到调用这个方法注册bean定义信息。     DefaultListableBeanFactory实现了BeanDefinitionRegistry  接口,可以看到它实现了关键的registerBeanDefinition用于将bean的定义注册到工厂类中,其中维护了一个Map用于存储bean的定义信息: public   void  registerBeanDefinition(String beanName, BeanDefinition beanDefinition)              throws  BeanDefinitionStoreException {         Assert.hasText(beanName,  " Bean name must not be empty " );         Assert.notNull(beanDefinition,  " Bean definition must not be null " );          if  (beanDefinition  instanceof  AbstractBeanDefinition) {              try  {                 ((AbstractBeanDefinition) beanDefinition).validate();             }              catch  (BeanDefinitionValidationException ex) {                  throw   new  BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,                          " Validation of bean definition failed " , ex);             }         }         Object oldBeanDefinition  =   this .beanDefinitionMap.get(beanName);          if  (oldBeanDefinition  !=   null ) {              if  ( ! isAllowBeanDefinitionOverriding()) {                  throw   new  BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,                          " Cannot register bean definition [ "   +  beanDefinition  +   " ] for bean ' "   +  beanName  +                          " ': there's already [ "   +  oldBeanDefinition  +   " ] bound " );             }              else  {                  if  (logger.isInfoEnabled()) {                     logger.info( " Overriding bean definition for bean ' "   +  beanName  +                              " ': replacing [ "   +  oldBeanDefinition  +   " ] with [ "   +  beanDefinition  +   " ] " );                 }             }         }          else  {              this .beanDefinitionNames.add(beanName);         }          this .beanDefinitionMap.put(beanName, beanDefinition);          //  Remove corresponding bean from singleton cache, if any.          //  Shouldn't usually be necessary, rather just meant for overriding          //  a context's default beans (e.g. the default StaticMessageSource          //  in a StaticApplicationContext).         removeSingleton(beanName);     }     beanDefinitionMap就是我们存储工厂类中注册的bean的信息,用bean name做为key: /**  Map of bean definition objects, keyed by bean name  */      private   final  Map beanDefinitionMap  =   new  HashMap();       DefaultListableBeanFactory 重写了 protected   abstract  BeanDefinition getBeanDefinition(String beanName)  throws  BeansException; 模板方法用于提供bean定义信息给getBean方法用于创建bean实例。getBeanDefinition的从beanDefinitionMap 查找bean定义即可: public  BeanDefinition getBeanDefinition(String beanName)  throws  NoSuchBeanDefinitionException {         BeanDefinition bd  = (BeanDefinition)  this .beanDefinitionMap.get(beanName);          if  (bd  ==   null ) {              if  (logger.isDebugEnabled()) {                 logger.debug( " No bean named ' "   +  beanName  +   " ' found in  "   +  toString());             }              throw   new  NoSuchBeanDefinitionException(beanName);         }          return  bd;     }     看到了这里是不是觉的有点糊涂,我还是建议有兴趣地找来spring1.2的源码来看看就很清晰了,充分利用eclipse的F3跳转结合上面的那张UML图。     OK,有了注册bean定义信息的方法(registerBeanDefinition),有了获取bean定义信息的方法(getBeanDefinition ),有了创建bean的方法(createBean),那么在哪里调用这些方法呢?createBean我们已经知道是在BeanFactory的getBean方法时调用,getBeanDefinition 又是在creatBean时调用用于获取bean的定义信息,那么注册bean定义信息的方法肯定是在xml文件解析阶段被调用。    XmlBeanFactory继承DefaultListableBeanFactory ,没有定义新的方法,只是有两个重载的构造函数:    public   class  XmlBeanFactory  extends  DefaultListableBeanFactory {    private   final  XmlBeanDefinitionReader reader  =   new  XmlBeanDefinitionReader( this );    public  XmlBeanFactory(Resource resource)  throws  BeansException {          this (resource,  null );     }    public  XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)  throws  BeansException {          super (parentBeanFactory);          this .reader.loadBeanDefinitions(resource);     } }     初始化XmlBeanFactory时调用XmlBeanDefinitionReader读取xml配置文件,而XmlBeanDefinitionReader的loadBeanDefinitions方法,载入xml文件并且调用XmlBeanDefinitionParser 解析xml文件同时注册bean定义信息到bean工厂,这几个类的协作以及它们继承体系也非常清晰,在此不再详述(累啊),XmlBeanDefinitionParser是一个接口,具体的实现类是org.springframework.beans.factory.xml.DefaultXmlBeanDefinitionParser,我们关注的就是它是怎么注册bean信息到bean工厂的: protected   int  parseBeanDefinitions(Element root)  throws  BeanDefinitionStoreException {           if  (IMPORT_ELEMENT.equals(node.getNodeName())) {                     importBeanDefinitionResource(ele);                 }                  else   if  (ALIAS_ELEMENT.equals(node.getNodeName())) {                     String name  =  ele.getAttribute(NAME_ATTRIBUTE);                     String alias  =  ele.getAttribute(ALIAS_ATTRIBUTE);                      this .beanDefinitionReader.getBeanFactory().registerAlias(name, alias);                 }                  else   if  (BEAN_ELEMENT.equals(node.getNodeName())) {                     beanDefinitionCount ++ ;                     BeanDefinitionHolder bdHolder  =  parseBeanDefinitionElement(ele,  false );                      // 关键代码,调用工具类将bean定义注册到beanFactory                     BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,  this .beanDefinitionReader.getBeanFactory());                 }     } 工具类BeanDefinitionReaderUtils中的注册方法:      public   static   void  registerBeanDefinition(             BeanDefinitionHolder bdHolder, BeanDefinitionRegistry beanFactory)  throws  BeansException {          //  Register bean definition under primary name.,注册bean         beanFactory.registerBeanDefinition(bdHolder.getBeanName(), bdHolder.getBeanDefinition());          //  Register aliases for bean name, if any.,注册别名          if  (bdHolder.getAliases()  !=   null ) {              for  ( int  i  =   0 ; i  <  bdHolder.getAliases().length; i ++ ) {                 beanFactory.registerAlias(bdHolder.getBeanName(), bdHolder.getAliases()[i]);             }         }     }

       注意这里的beanFactory是BeanDefinitionRegistry类型 ,DefaultListableBeanFactory实现了这个接口。     更多内容,比如spring是怎么把bean的属性注入的?答案在BeanWrapperImpl中的一系列setPropertyXXX方法。BeanFactory是如何实例化bean的呢?具体展开请看org.springframework.beans.factory.support.InstantiationStrategy 接口,一个典型的策略模式的应用,两个实现类:SimpleInstantiationStrategy和CglibSubclassingInstantiationStrategy。我们知道spring有3种注入方式:setter、构造函数以及Method Inject。这里的CglibSubclassingInstantiationStrategy使用cglib库用于实现method inject。这样一篇小文容不下这么多内容,还是有兴趣的自己找源码读读。     写到这里,我对自己的文字表达能力产生怀疑,我能不能把这些所有的信息都说清楚呢?感觉很不满意,将就吧,也算是自己的学习总结。     读spring源码这段时间,最深的几点体会: 1)单元测试非常重要,充分感受到了单元测试作为项目文档的优势。看不懂一个类,找到这个类的测试类就OK! 2)针对接口编程的原则,spring处处体现了这个原则,繁多的接口带来的是松耦合、高内聚并且易于扩展的架构,但也带来了一定的理解难度。作为通用型框架也许需要这么考虑,在实际项目中的取舍还是要自己把握。 3)设计模式的使用,spring中应用了很多模式,比如template method,比如strategy和factory method、visitor、singleton等,简直是一本模式实践的良好教材。

    文章转自庄周梦蝶  ,原文发布时间5.17

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)