• Spring bean加载2--FactoryBean情况处理


    Spring bean加载2--FactoryBean情况处理

    在Spring bean加载过程中,每次bean实例在返回前都会调用getObjectForBeanInstance来处理FactoryBean的情况.
    这边的FactoryBean,Spring设计用于新建复杂bean的,联想下GOF设计模式的创建型,一样的为了解决复杂的bean实例化过程.
    其实这边的FactoryBean就是一个factory method[gof定义的意图:定义一个用于创建对象的接口,让子类决定实例化哪个类.Factory Method使一个类的实例化延迟到其子类].

    这边的处理主要涉及3个方法,我们来看看3个方法各自的职责:

    1. getObjectForBeanInstance: 参数校验之类的准备工作
    2. getObjectFromFactoryBean: 单例时,确保实例是全局唯一的
    3. doGetObjectFromFactoryBean: 实实在在的实例化

    参数校验之类的准备工作##

    AbstractBeanFactory的getObjectForBeanInstance处理.

    1. 如果name制定要获取FactoryBean本身实例,而beanInstance却又不是FactoryBean,直接抛异常
    2. 如果不需要调用getObject实例化,直接返回实例
    3. 尝试从缓存中获取实例[FactoryBeanRegistrySupport负责]
    4. 准备beanDefinition,委托getObjectFromFactoryBean处理

    单例时保障实例全局唯一##

    FactoryBeanRegistrySupport的getObjectFromFactoryBean处理
    FactoryBeanRegistrySupport负责FactoryBean相关的操作,并缓存FactoryBean的getObject实例化的bean.

    1. 判断factory是单例,同时已经new好了(后面需要调用getObject获取目标对象,这边需要factory已经实例化)
    2. 单例时,先尝试去缓存找;如果找不到或者不是单例,委托doGetObjectFromFactoryBean实例化一个
    3. 由于这样新建就没有机会调用BeanPostProcessor了,所以这边直接调用其postProcessAfterInitialization[职责职责职责,AbstractAutowireCapableBeanFactory干的]
    4. 缓冲得到的实例

    实例化,干活的##

    FactoryBeanRegistrySupport的doGetObjectFromFactoryBean处理
    这边做的事很少,就是调用factoryBean的getObject,然后如果实例化得到的对象为空抛异常.

    源码摘要##

    AbstractBeanFactory

    /**
     * Get the object for the given bean instance, either the bean
     * instance itself or its created object in case of a FactoryBean.
     * 返回bean 实例的对象,可能是实例本身,也可能是FactoryBean新建的对象
     * @param beanInstance the shared bean instance
     * @param name name that may include factory dereference prefix
     * @param beanName the canonical bean name
     * @param mbd the merged bean definition
     * @return the object to expose for the bean
     */
    protected Object getObjectForBeanInstance(
    		Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
    
        // 如果想要获取FactoryBean本身,那么beanInstance必须是FactoryBean的实例
    	// 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());
    	}
    
        // 如果instance不是FactoryBean实例,或者想要获取的就是FactoryBean实例,那么直接返回就好
    	// 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) {
            // 缓存中没有对象,那么从头准备bean defition实例化一个
    		// 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;
    }
    

    FactoryBeanRegistrySupport

    /**
     * Obtain an object to expose from the given FactoryBean, if available
     * in cached form. Quick check for minimal synchronization.
     * 获取缓存的,通过FactoryBean暴露出来的对象
     * @param beanName the name of the bean
     * @return the object obtained from the FactoryBean,
     * or {@code null} if not available
     */
    protected Object getCachedObjectForFactoryBean(String beanName) {
    	Object object = this.factoryBeanObjectCache.get(beanName);
        // 类似<重构>中Introduce NUll Object,只是这边的NULL_OBJECT是Object类型的,没有解决Martin说的"不需要询问对象类型,就可以直接调用行为的方法"
    	return (object != NULL_OBJECT ? object : null);
    }
    
    /**
     * Obtain an object to expose from the given FactoryBean.
     * @param factory the FactoryBean instance
     * @param beanName the name of the bean
     * @param shouldPostProcess whether the bean is subject to post-processing
     * @return the object obtained from the FactoryBean
     * @throws BeanCreationException if FactoryBean object creation failed
     * @see org.springframework.beans.factory.FactoryBean#getObject()
     */
    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        // factory是单例的同时,还得已经被实例化(感觉这个检验怪怪的,没想明白)
    	if (factory.isSingleton() && containsSingleton(beanName)) {
    		synchronized (getSingletonMutex()) {
    			Object object = this.factoryBeanObjectCache.get(beanName);
    			if (object == null) {
                    // 缓存中找不到,就自己干吧,实例化
    				object = doGetObjectFromFactoryBean(factory, beanName);
    				// Only post-process and store if not put there already during getObject() call above
    				// (e.g. because of circular reference processing triggered by custom getBean calls)
    				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
    				if (alreadyThere != null) {
    					object = alreadyThere;
    				}
    				else {
    					if (object != null && shouldPostProcess) {
    						try {
                                // 外面BeanPostProcessor作用在factory上,没有作用在实际想要的实例上,这边补一个
                                // 也就是说,BeanPostProcessor的postProcessBeforeInitialization不会作用在FactoryBean上
    							object = postProcessObjectFromFactoryBean(object, beanName);
    						}
    						catch (Throwable ex) {
    							throw new BeanCreationException(beanName,
    									"Post-processing of FactoryBean's singleton object failed", ex);
    						}
    					}
                        // 缓存
    					this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
    				}
    			}
    			return (object != NULL_OBJECT ? object : null);
    		}
    	}
    	else {
    		Object object = doGetObjectFromFactoryBean(factory, beanName);
    		if (object != null && shouldPostProcess) {
    			try {
    				object = postProcessObjectFromFactoryBean(object, beanName);
    			}
    			catch (Throwable ex) {
    				throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
    			}
    		}
    		return object;
    	}
    }
    
    /**
     * Obtain an object to expose from the given FactoryBean.
     * @param factory the FactoryBean instance
     * @param beanName the name of the bean
     * @return the object obtained from the FactoryBean
     * @throws BeanCreationException if FactoryBean object creation failed
     * @see org.springframework.beans.factory.FactoryBean#getObject()
     */
    private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
    		throws BeanCreationException {
    
    	Object object;
    	try {
    		if (System.getSecurityManager() != null) {
    			AccessControlContext acc = getAccessControlContext();
    			try {
    				object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
    					@Override
    					public Object run() throws Exception {
    							return factory.getObject();
    						}
    					}, acc);
    			}
    			catch (PrivilegedActionException pae) {
    				throw pae.getException();
    			}
    		}
    		else {
    			object = factory.getObject();
    		}
    	}
    	catch (FactoryBeanNotInitializedException ex) {
    		throw new BeanCurrentlyInCreationException(beanName, ex.toString());
    	}
    	catch (Throwable ex) {
    		throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
    	}
    
    	// Do not accept a null value for a FactoryBean that's not fully
    	// initialized yet: Many FactoryBeans just return null then.
    	if (object == null && isSingletonCurrentlyInCreation(beanName)) {
    		throw new BeanCurrentlyInCreationException(
    				beanName, "FactoryBean which is currently in creation returned null from getObject");
    	}
    	return object;
    }
    /**
     * Post-process the given object that has been obtained from the FactoryBean.
     * The resulting object will get exposed for bean references.
     * <p>The default implementation simply returns the given object as-is.
     * Subclasses may override this, for example, to apply post-processors.
     * @param object the object obtained from the FactoryBean.
     * @param beanName the name of the bean
     * @return the object to expose
     * @throws org.springframework.beans.BeansException if any post-processing failed
     */
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
    	return object;
    }
    

    AbstractAutowireCapableBeanFactory

    /**
     * Applies the {@code postProcessAfterInitialization} callback of all
     * registered BeanPostProcessors, giving them a chance to post-process the
     * object obtained from FactoryBeans (for example, to auto-proxy them).
     * @see #applyBeanPostProcessorsAfterInitialization
     */
    @Override
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
    	return applyBeanPostProcessorsAfterInitialization(object, beanName);
    }
    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    		throws BeansException {
    
    	Object result = existingBean;
    	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    		result = beanProcessor.postProcessAfterInitialization(result, beanName);
    		if (result == null) {
    			return result;
    		}
    	}
    	return result;
    }
    
  • 相关阅读:
    nuxt.js 引入第三方插件报window is not defined
    webstorm 设置js或者html文件自动缩进为4个空格不生效
    调用接口缓存数据
    node 版本更新
    监听2个值的变化,后执行方法
    去除空格
    Redis6详解(四)——配置文件
    Dubbo(一)——
    MybatisPlus(四)——
    数据结构与算法(九)——查找
  • 原文地址:https://www.cnblogs.com/leftthen/p/5453354.html
Copyright © 2020-2023  润新知