• 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缓存起来。代码就不贴了。

  • 相关阅读:
    python之连接oracle数据库
    从一副牌中随机抽一张牌
    判断一个点是否在圆内
    判断每个月有多少天
    猜数字游戏
    求一元二次方程的2个跟
    Servlet细节处理
    Servlet
    Http协议
    Struts2(2)
  • 原文地址:https://www.cnblogs.com/heyanan/p/6086641.html
Copyright © 2020-2023  润新知