BeanDefinition到Bean


轉自:http://songzi0206.iteye.com/blog/1430239

當 BeanDefinition 注冊完畢以后, Spring Bean 工廠就可以隨時根據需要進行實例化了。對於XmlBeanFactory 來說,實例化默認是延遲進行的,也就是說在 getBean 的時候才會;而對於 ApplicationContext來說,實例化會在容器啟動后通過 AbstractApplicationContext 中 reflash 方法自動進行,主要經過方法鏈:reflesh()   à finishBeanFactoryInitialization (factory) à DefaultListableBeanFactory.preInstantiateSingletons (), 在這里會根據注冊的 BeanDefinition 信息依此調用 getBean(beanName) 。而真正實例化的邏輯和 BeanFactory 是“殊途同歸”的,所有有關 Bean 實例化都可以從 getBean(beanName) 入手。

      AbstractBeanFactory 有四個 getBean 的重載方法,不管調用哪個方法最終都是會調用另一個 doGetBean 方法:

Java代碼   收藏代碼
  1. public Object getBean(String name) throws BeansException {  
  2.         return getBean(name, null, null);  
  3.     }  
  4.           
  5.     public Object getBean(String name, Class requiredType) throws BeansException {  
  6.         return getBean(name, requiredType, null);  
  7.     }  
  8.   
  9.     public Object getBean(String name, Object[] args) throws BeansException {  
  10.         return getBean(name, null, args);  
  11.     }  
  12.   
  13.     /** 
  14.      * Return an instance, which may be shared or independent, of the specified bean. 
  15.      * @param name the name of the bean to retrieve 
  16.      * @param requiredType the required type of the bean to retrieve 
  17.      * @param args arguments to use if creating a prototype using explicit arguments to a 
  18.      * static factory method. It is invalid to use a non-null args value in any other case. 
  19.      * @return an instance of the bean 
  20.      * @throws BeansException if the bean could not be created 
  21.      */  
  22.     public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {  
  23.         return doGetBean(name, requiredType, args, false);  
  24.     }  

        doGetBean方法比較長一點,見下面注釋:

Java代碼   收藏代碼
  1. protected Object doGetBean(  
  2. final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)   
  3. throws BeansException {  
  4. //bean name處理,去除FactoryBean前綴等  
  5.      final String beanName = transformedBeanName(name);  
  6.      Object bean = null;  
  7.   
  8. //先從singleton緩存中查看是否已經實例化過該Bean,根據是否有緩存分為兩個分支分別處理  
  9.     Object sharedInstance = getSingleton(beanName);  
  10.     if (sharedInstance != null && args == null) {  
  11. // 分支一,若緩存中獲取到了並且該BeanDefinition信息表明該bean是singleton的,直接將獲取到的緩存Bean  
  12. //(有可能是半成品)交給getObjectForBeanInstance處理  
  13.  /*.........省略logger部分代碼............*/  
  14. //調用getObjectForBeanInstance處理  
  15.      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  
  16.     }else {  
  17. // 分之二:沒有緩存,則需要從頭實例化該bean  
  18.             // We're assumably within a circular reference.  
  19.       if (isPrototypeCurrentlyInCreation(beanName)) {   
  20.            throw new BeanCurrentlyInCreationException(beanName);}  
  21.   
  22. // 檢查BeanDefinition是否在當前工廠或父工廠  
  23.             BeanFactory parentBeanFactory = getParentBeanFactory();  
  24.             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  
  25.                 // Not found -> check parent.  
  26.                 String nameToLookup = originalBeanName(name);  
  27.                 if (args != null) {  
  28. // 父工廠getBean  
  29.                     return parentBeanFactory.getBean(nameToLookup, args);  
  30.                 }  
  31.                 else {  
  32.                     // No args -> delegate to standard getBean method.  
  33.                     return parentBeanFactory.getBean(nameToLookup, requiredType);  
  34.                 }  
  35.             }  
  36. //將bean加入“正在創建”的集合,完成后會remove,對應afterSingletonCreation/afterPrototypeCreation方法  
  37.             if (!typeCheckOnly) {  
  38.                 markBeanAsCreated(beanName);  
  39.             }  
  40.   
  41.             final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  
  42.             checkMergedBeanDefinition(mbd, beanName, args);  
  43.   
  44. // 解決依賴關系,將依賴的bean提前實例化  
  45.             String[] dependsOn = mbd.getDependsOn();  
  46.             if (dependsOn != null) {  
  47.                 for (int i = 0; i < dependsOn.length; i++) {  
  48.                     String dependsOnBean = dependsOn[i];  
  49.                     getBean(dependsOnBean);  
  50.                     registerDependentBean(dependsOnBean, beanName);  
  51.                 }  
  52.             }  
  53.   
  54. // 這里又需要根據bean的類型分為三種情況:singleton、prototype、request/session  
  55.             if (mbd.isSingleton()) {  
  56.                            //通過自定義ObjectFactory實例化Bean,此結果可能是半成品(是FactoryBean等)  
  57.                 sharedInstance = getSingleton(beanName, new ObjectFactory() {  
  58.                     public Object getObject() throws BeansException {  
  59.                         try {  
  60.                           //真正實例化裝配的邏輯在createBean方法中  
  61.                             return createBean(beanName, mbd, args);  
  62.                         }  
  63.                         catch (BeansException ex) {  
  64.             // Explicitly remove instance from singleton cache: It might have been put there  
  65.             // eagerly by the creation process, to allow for circular reference resolution.  
  66.             // Also remove any beans that received a temporary reference to the bean.  
  67.                             destroySingleton(beanName);  
  68.                             throw ex;  
  69.                         }  
  70.                     }  
  71.                 });  
  72.                         //上一步半成品的Bean交給getObjectForBeanInstance方法處理  
  73.                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  
  74.             }  
  75.   
  76.             else if (mbd.isPrototype()) {  
  77.                 // It's a prototype -> create a new instance.  
  78.                 Object prototypeInstance = null;  
  79.                 try {  
  80.                     beforePrototypeCreation(beanName);  
  81.                      //真正實例化裝配的邏輯在createBean方法中  
  82.                     prototypeInstance = createBean(beanName, mbd, args);  
  83.                 }  
  84.                 finally {  
  85.                     afterPrototypeCreation(beanName);  
  86.                 }  
  87.                     //上一步半成品的Bean交給getObjectForBeanInstance方法處理  
  88.                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);  
  89.             }  
  90.   
  91.             else {  
  92.                             //request、session 的bean  
  93.                 String scopeName = mbd.getScope();  
  94.                 final Scope scope = (Scope) this.scopes.get(scopeName);  
  95.                 if (scope == null) {  
  96.         throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");  
  97.                 }  
  98.                 try {  
  99.                     Object scopedInstance = scope.get(beanName, new ObjectFactory() {  
  100.                         public Object getObject() throws BeansException {  
  101.                             beforePrototypeCreation(beanName);  
  102.                             try {  
  103.                          //真正實例化裝配的邏輯在createBean方法中  
  104.                                 return createBean(beanName, mbd, args);  
  105.                             }  
  106.                             finally {  
  107.                                 afterPrototypeCreation(beanName);  
  108.                             }  
  109.                         }  
  110.                     });  
  111.                        //上一步半成品的Bean交給getObjectForBeanInstance方法處理  
  112.                 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);  
  113.                 }  
  114.                 catch (IllegalStateException ex) {  
  115.                     throw new BeanCreationException(beanName,  
  116.                 "Scope '" + scopeName + "' is not active for the current thread; " +  
  117.     "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",  
  118.                             ex);  
  119.                 }  
  120.             }  
  121.         }  
  122.   
  123.         // Check if required type matches the type of the actual bean instance.  
  124.         if (requiredType != null && bean != null &&  
  125.                               !requiredType.isAssignableFrom(bean.getClass())) {  
  126.             throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());  
  127.         }  
  128.         return bean;  
  129.     }  

 

      通過注釋,可以整理出較清晰的邏輯: 檢查Bean緩存,已經有緩存的Bean對象(有可能是半成品)則交給getObjectForBeanInstance方法處理;否則先根據Bean的生命周期類型分別實例化,每種情況大致都分兩步,第一步都交給createBean方法生產一個半成品的bean對象,然后同樣是將半成品的bean交給getObjectForBeanInstance方法處理。所以關鍵的邏輯就在這兩個方法了,下面以singleton為例看看這兩個方法,具體代碼:

 

Java代碼   收藏代碼
  1. sharedInstance = getSingleton(beanName, new ObjectFactory() {  
  2.                     public Object getObject() throws BeansException {  
  3.                         try {  
  4.                             return createBean(beanName, mbd, args);  
  5.                         }  
  6.                         catch (BeansException ex) {  
  7.                             // Explicitly remove instance from singleton cache: It might have been put there  
  8.                             // eagerly by the creation process, to allow for circular reference resolution.  
  9.                             // Also remove any beans that received a temporary reference to the bean.  
  10.                             destroySingleton(beanName);  
  11.                             throw ex;  
  12.                         }  
  13.                     }  
  14.                 });  
  15. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  

       getSingleton方法做的工作主要是實例化bean之前和之后回調beforeSingletonCreation/afterSingletonCreation、實例化bean、以及將bean對象緩存起來,具體實例化bean是通過回調匿名對象ObjectFactory的getObject方法實現的,從代碼中明顯看到主要是createBean方法。這里要特別注意下,緩存的bean對象是createBean生產的,這個方法生產的bean只是“半成品”,有可能是個factoryBean,真正返回給客戶端使用的bean還必須進行下一步getObjectBeanInstance處理。所以緩存的bean對象可以認為是“半成品”,這就和前文代碼中的注釋相呼應(緩存中若取到了bean,必須進行getObjectBeanInstance處理)。

 

     對createBean方法實際上在“Spring IOC之BeanFactory”中已經有過分析,所以流程就不再簡單重復,直接按步驟:

1.  resolveBeanClass(mbd, beanName);

2.  mbd.prepareMethodOverrides();//Spring IOC之BeanFactory已有解釋,不重復

3.  Object bean = resolveBeforeInstantiation(beanName, mbd);

      解釋下,這里主要對於一些代理的bean做處理,我們平常經常會配置一些AOP模塊,對於需要aop增強的bean實際上都會經過spring代理織入,而這些bean的代理邏輯應該就在這里處理了,具體看看這部分的代碼:

Java代碼   收藏代碼
  1. /** 
  2.      * Apply before-instantiation post-processors, resolving whether there is a 
  3.      * before-instantiation shortcut for the specified bean. 
  4.      * @param beanName the name of the bean 
  5.      * @param mbd the bean definition for the bean 
  6.      * @return the shortcut-determined bean instance, or <code>null</code> if none 
  7.      */  
  8.     protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {  
  9.         Object bean = null;  
  10.         if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {  
  11.             // Make sure bean class is actually resolved at this point.  
  12.             if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  
  13.                 bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);  
  14.                 if (bean != null) {  
  15.                     bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);  
  16.                 }  
  17.             }  
  18.             mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null);  
  19.         }  
  20.         return bean;  
  21.     }  
  22.   
  23. /** 
  24.      * Apply InstantiationAwareBeanPostProcessors to the specified bean definition 
  25.      * (by class and name), invoking their <code>postProcessBeforeInstantiation</code> methods. 
  26.      * <p>Any returned object will be used as the bean instead of actually instantiating 
  27.      * the target bean. A <code>null</code> return value from the post-processor will 
  28.      * result in the target bean being instantiated. 
  29.      * @param beanClass the class of the bean to be instantiated 
  30.      * @param beanName the name of the bean 
  31.      * @return the bean object to use instead of a default instance of the target bean, or <code>null</code> 
  32.      * @throws BeansException if any post-processing failed 
  33.      * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 
  34.      */  
  35.     protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName)  
  36.             throws BeansException {  
  37.   
  38.         for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {  
  39.             BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();  
  40.             if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {  
  41.                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;  
  42.                 Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);  
  43.                 if (result != null) {  
  44.                     return result;  
  45.                 }  
  46.             }  
  47.         }  
  48.         return null;  
  49.     }  
  50.   
  51. //AbstractAutoProxyCreator  
  52. public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {  
  53.         Object cacheKey = getCacheKey(beanClass, beanName);  
  54.   
  55.         if (!this.targetSourcedBeans.contains(cacheKey)) {  
  56.             if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) {  
  57.                 return null;  
  58.             }  
  59.             if (isInfrastructureClass(beanClass, beanName) || shouldSkip(beanClass, beanName)) {  
  60.                 this.nonAdvisedBeans.add(cacheKey);  
  61.                 return null;  
  62.             }  
  63.         }  
  64.   
  65.         // Create proxy here if we have a custom TargetSource.  
  66.         // Suppresses unnecessary default instantiation of the target bean:  
  67.         // The TargetSource will handle target instances in a custom fashion.  
  68.         TargetSource targetSource = getCustomTargetSource(beanClass, beanName);  
  69.         if (targetSource != null) {  
  70.             this.targetSourcedBeans.add(beanName);  
  71.             Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);  
  72.             Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);  
  73.             this.proxyTypes.put(cacheKey, proxy.getClass());  
  74.             return proxy;  
  75.         }  
  76.   
  77.         return null;  
  78.     }  

          對於AutoProxy部分代碼要放到spring aop部分中去寫了,這里只要明白如果是代理bean在postProcessBeforeInstantiation階段會返回一個proxy,這時候bean已經算是實例化好了,再調用applyBeanPostProcessorsAfterInitialization即BeanPostProcessor.postProcessAfterInitialization回調進行屬性的設置。最后的結果就可以返回bean對象了,只是一個Proxy Bean Object.

 

 4.  Object beanInstance = doCreateBean(beanName, mbd, args);//如果是代理bean就不會走到這一步

       解釋下:對於非代理的bean,基本上實例化的邏輯就在doCreateBean這個方法了,這個方法在“Spring IOC之BeanFactory”中已經有過分析,所以不重復解釋了,貼一個bean生命周期的流程圖做為createBean方法的結尾:


             上圖不是我所畫,來源於spring IOC容器介紹。

 

       半成品出來之后還需要調用getObjectForBeanInstance進一步處理,這個方法:

Java代碼   收藏代碼
  1. protected Object getObjectForBeanInstance(  
  2.             Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {  
  3.   
  4.         // Don't let calling code try to dereference the factory if the bean isn't a factory.  
  5.         if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {  
  6.             throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());  
  7.         }  
  8.   
  9.         // Now we have the bean instance, which may be a normal bean or a FactoryBean.  
  10.         // If it's a FactoryBean, we use it to create a bean instance, unless the  
  11.         // caller actually wants a reference to the factory.  
  12.         if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {  
  13.             return beanInstance;  
  14.         }  
  15.   
  16.         Object object = null;  
  17.         if (mbd == null) {  
  18.             object = getCachedObjectForFactoryBean(beanName);  
  19.         }  
  20.         if (object == null) {  
  21.             // Return bean instance from factory.  
  22.             FactoryBean factory = (FactoryBean) beanInstance;  
  23.             // Caches object obtained from FactoryBean if it is a singleton.  
  24.             if (mbd == null && containsBeanDefinition(beanName)) {  
  25.                 mbd = getMergedLocalBeanDefinition(beanName);  
  26.             }  
  27.             boolean synthetic = (mbd != null && mbd.isSynthetic());  
  28.             object = getObjectFromFactoryBean(factory, beanName, !synthetic);  
  29.         }  
  30.         return object;  
  31.     }  

       開始部分是邏輯檢查,是否是FactoryBean,后面是從factoryBean中獲取實際的Bean。獲取bean也是先檢查緩存,沒有緩存再getObjectFromFactoryBean獲取,詳細再doGetObjectFromFactoryBean方法中,最后將獲取的bean緩存起來。代碼就不貼了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM