zoukankan      html  css  js  c++  java
  • BeanDefinition到Bean

    当 BeanDefinition 注册完毕以后, Spring Bean 工厂就可以随时根据需要进行实例化了。对于 XmlBeanFactory 来说,实例化默认是延迟进行的,也就是说在 getBean 的时候才会;而对于 ApplicationContext 来说,实例化会在容器启动后通过 AbstractApplicationContext 中 reflash 方法自动进行,主要经过方法链: reflesh() à finishBeanFactoryInitialization (factory) à DefaultListableBeanFactory.preInstantiateSingletons (), 在这里会根据注册的 BeanDefinition 信息依此调用 getBean(beanName) 。而真正实例化的逻辑和 BeanFactory 是“殊途同归”的,所有有关 Bean 实例化都可以从 getBean(beanName) 入手。

    AbstractBeanFactory 有四个 getBean 的重载方法,不管调用哪个方法最终都是会调用另一个 doGetBean 方法: 
    

     java代码:

     public Object getBean(String name) throws BeansException {  
                return getBean(name, null, null);  
            }  
    
            public Object getBean(String name, Class requiredType) throws BeansException {  
                return getBean(name, requiredType, null);  
            }  
    
            public Object getBean(String name, Object[] args) throws BeansException {  
                return getBean(name, null, args);  
            }  
    
            /** 
             * Return an instance, which may be shared or independent, of the specified bean. 
             * @param name the name of the bean to retrieve 
             * @param requiredType the required type of the bean to retrieve 
             * @param args arguments to use if creating a prototype using explicit arguments to a 
             * static factory method. It is invalid to use a non-null args value in any other case. 
             * @return an instance of the bean 
             * @throws BeansException if the bean could not be created 
             */  
            public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {  
                return doGetBean(name, requiredType, args, false);  
    }  
    

    doGetBean方法比较长一点,见下面注释:

    Java代码

     protected Object doGetBean(  
        final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)   
        throws BeansException {  
        //bean name处理,去除FactoryBean前缀等  
             final String beanName = transformedBeanName(name);  
             Object bean = null;  
    
        //先从singleton缓存中查看是否已经实例化过该Bean,根据是否有缓存分为两个分支分别处理  
            Object sharedInstance = getSingleton(beanName);  
            if (sharedInstance != null && args == null) {  
        // 分支一,若缓存中获取到了并且该BeanDefinition信息表明该bean是singleton的,直接将获取到的缓存Bean  
        //(有可能是半成品)交给getObjectForBeanInstance处理  
         /*.........省略logger部分代码............*/  
        //调用getObjectForBeanInstance处理  
             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  
            }else {  
        // 分之二:没有缓存,则需要从头实例化该bean  
                    // We're assumably within a circular reference.  
              if (isPrototypeCurrentlyInCreation(beanName)) {   
                   throw new BeanCurrentlyInCreationException(beanName);}  
    
        // 检查BeanDefinition是否在当前工厂或父工厂  
                    BeanFactory parentBeanFactory = getParentBeanFactory();  
                    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  
                        // Not found -> check parent.  
                        String nameToLookup = originalBeanName(name);  
                        if (args != null) {  
        // 父工厂getBean  
                            return parentBeanFactory.getBean(nameToLookup, args);  
                        }  
                        else {  
                            // No args -> delegate to standard getBean method.  
                            return parentBeanFactory.getBean(nameToLookup, requiredType);  
                        }  
                    }  
        //将bean加入“正在创建”的集合,完成后会remove,对应afterSingletonCreation/afterPrototypeCreation方法  
                    if (!typeCheckOnly) {  
                        markBeanAsCreated(beanName);  
                    }  
    
                    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  
                    checkMergedBeanDefinition(mbd, beanName, args);  
    
        // 解决依赖关系,将依赖的bean提前实例化  
                    String[] dependsOn = mbd.getDependsOn();  
                    if (dependsOn != null) {  
                        for (int i = 0; i < dependsOn.length; i++) {  
                            String dependsOnBean = dependsOn[i];  
                            getBean(dependsOnBean);  
                            registerDependentBean(dependsOnBean, beanName);  
                        }  
                    }  
    
        // 这里又需要根据bean的类型分为三种情况:singleton、prototype、request/session  
                    if (mbd.isSingleton()) {  
                                   //通过自定义ObjectFactory实例化Bean,此结果可能是半成品(是FactoryBean等)  
                        sharedInstance = getSingleton(beanName, new ObjectFactory() {  
                            public Object getObject() throws BeansException {  
                                try {  
                                  //真正实例化装配的逻辑在createBean方法中  
                                    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方法处理  
                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  
                    }  
    
                    else if (mbd.isPrototype()) {  
                        // It's a prototype -> create a new instance.  
                        Object prototypeInstance = null;  
                        try {  
                            beforePrototypeCreation(beanName);  
                             //真正实例化装配的逻辑在createBean方法中  
                            prototypeInstance = createBean(beanName, mbd, args);  
                        }  
                        finally {  
                            afterPrototypeCreation(beanName);  
                        }  
                            //上一步半成品的Bean交给getObjectForBeanInstance方法处理  
                       bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);  
                    }  
    
                    else {  
                                    //request、session 的bean  
                        String scopeName = mbd.getScope();  
                        final 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 {  
                                    beforePrototypeCreation(beanName);  
                                    try {  
                                 //真正实例化装配的逻辑在createBean方法中  
                                        return createBean(beanName, mbd, args);  
                                    }  
                                    finally {  
                                        afterPrototypeCreation(beanName);  
                                    }  
                                }  
                            });  
                               //上一步半成品的Bean交给getObjectForBeanInstance方法处理  
                        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);  
                        }  
                    }  
                }  
    
                // Check if required type matches the type of the actual bean instance.  
                if (requiredType != null && bean != null &&  
                                      !requiredType.isAssignableFrom(bean.getClass())) {  
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());  
                }  
                return bean;  
    }  
    

    通过注释,可以整理出较清晰的逻辑: 检查Bean缓存,已经有缓存的Bean对象(有可能是半成品)则交给getObjectForBeanInstance方法处理;否则先根据Bean的生命周期类型分别实例化,每种情况大致都分两步,第一步都交给createBean方法生产一个半成品的bean对象,然后同样是将半成品的bean交给getObjectForBeanInstance方法处理。所以关键的逻辑就在这两个方法了,下面以singleton为例看看这两个方法,具体代码:

    Java代码

     sharedInstance = getSingleton(beanName, new ObjectFactory() {  
                            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);  
    

     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代码

     /** 
             * Apply before-instantiation post-processors, resolving whether there is a 
             * before-instantiation shortcut for the specified bean. 
             * @param beanName the name of the bean 
             * @param mbd the bean definition for the bean 
             * @return the shortcut-determined bean instance, or <code>null</code> if none 
             */  
            protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {  
                Object bean = null;  
                if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {  
                    // Make sure bean class is actually resolved at this point.  
                    if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  
                        bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);  
                        if (bean != null) {  
                            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);  
                        }  
                    }  
                    mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null);  
                }  
                return bean;  
            }  
    
        /** 
             * Apply InstantiationAwareBeanPostProcessors to the specified bean definition 
             * (by class and name), invoking their <code>postProcessBeforeInstantiation</code> methods. 
             * <p>Any returned object will be used as the bean instead of actually instantiating 
             * the target bean. A <code>null</code> return value from the post-processor will 
             * result in the target bean being instantiated. 
             * @param beanClass the class of the bean to be instantiated 
             * @param beanName the name of the bean 
             * @return the bean object to use instead of a default instance of the target bean, or <code>null</code> 
             * @throws BeansException if any post-processing failed 
             * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 
             */  
            protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName)  
                    throws BeansException {  
    
                for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {  
                    BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();  
                    if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {  
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;  
                        Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);  
                        if (result != null) {  
                            return result;  
                        }  
                    }  
                }  
                return null;  
            }  
    
        //AbstractAutoProxyCreator  
        public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {  
                Object cacheKey = getCacheKey(beanClass, beanName);  
    
                if (!this.targetSourcedBeans.contains(cacheKey)) {  
                    if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) {  
                        return null;  
                    }  
                    if (isInfrastructureClass(beanClass, beanName) || shouldSkip(beanClass, beanName)) {  
                        this.nonAdvisedBeans.add(cacheKey);  
                        return null;  
                    }  
                }  
    
                // Create proxy here if we have a custom TargetSource.  
                // Suppresses unnecessary default instantiation of the target bean:  
                // The TargetSource will handle target instances in a custom fashion.  
                TargetSource targetSource = getCustomTargetSource(beanClass, beanName);  
                if (targetSource != null) {  
                    this.targetSourcedBeans.add(beanName);  
                    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);  
                    Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);  
                    this.proxyTypes.put(cacheKey, proxy.getClass());  
                    return proxy;  
                }  
    
                return null;  
    }  
    

    对于AutoProxy部分代码要放到spring aop部分中去写了,这里只要明白如果是代理bean在postProcessBeforeInstantiation阶段会返回一个proxy,这时候bean已经算是实例化好了,再调用applyBeanPostProcessorsAfterInitialization即BeanPostProcessor.postProcessAfterInitialization回调进行属性的设置。最后的结果就可以返回bean对象了,只是一个Proxy Bean Object.

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

    解释下:对于非代理的bean,基本上实例化的逻辑就在doCreateBean这个方法了,这个方法在“Spring IOC之BeanFactory”中已经有过分析,所以不重复解释了,贴一个bean生命周期的流程图做为createBean方法的结尾:

    上图不是我所画,来源于spring IOC容器介绍。

    半成品出来之后还需要调用getObjectForBeanInstance进一步处理,这个方法:

    protected Object getObjectForBeanInstance(  
                    Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {  
    
                // Don't let calling code try to dereference the factory if the bean isn't a factory.  
                if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {  
                    throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());  
                }  
    
                // Now we have the bean instance, which may be a normal bean or a FactoryBean.  
                // If it's a FactoryBean, we use it to create a bean instance, unless the  
                // caller actually wants a reference to the factory.  
                if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {  
                    return beanInstance;  
                }  
    
                Object object = null;  
                if (mbd == null) {  
                    object = getCachedObjectForFactoryBean(beanName);  
                }  
                if (object == null) {  
                    // Return bean instance from factory.  
                    FactoryBean factory = (FactoryBean) beanInstance;  
                    // Caches object obtained from FactoryBean if it is a singleton.  
                    if (mbd == null && containsBeanDefinition(beanName)) {  
                        mbd = getMergedLocalBeanDefinition(beanName);  
                    }  
                    boolean synthetic = (mbd != null && mbd.isSynthetic());  
                    object = getObjectFromFactoryBean(factory, beanName, !synthetic);  
                }  
                return object;  
    }  
    

     开始部分是逻辑检查,是否是FactoryBean,后面是从factoryBean中获取实际的Bean。获取bean也是先检查缓存,没有缓存再getObjectFromFactoryBean获取,详细再doGetObjectFromFactoryBean方法中,最后将获取的bean缓存起来。代码就不贴了。

  • 相关阅读:
    POJ 1659 Frogs' Neighborhood
    zoj 2913 Bus Pass(BFS)
    ZOJ 1008 Gnome Tetravex(DFS)
    POJ 1562 Oil Deposits (DFS)
    zoj 2165 Red and Black (DFs)poj 1979
    hdu 3954 Level up
    sgu 249 Matrix
    hdu 4417 Super Mario
    SPOJ (BNUOJ) LCM Sum
    hdu 2665 Kth number 划分树
  • 原文地址:https://www.cnblogs.com/MaxElephant/p/8086867.html
Copyright © 2011-2022 走看看