Spring bean加载2--FactoryBean情况解决
发布时间:2021-12-10 16:36:34 所属栏目:PHP教程 来源:互联网
导读:在Spring bean加载过程中,每次bean实例在返回前都会调用getObjectForBeanInstance来处理FactoryBean的情况. 这边的FactoryBean,Spring设计用于新建复杂bean的,联想下GOF设计模式的创建型,一样的为了解决复杂的bean实例化过程. 其实这边的FactoryBean就是一个
在Spring bean加载过程中,每次bean实例在返回前都会调用getObjectForBeanInstance来处理FactoryBean的情况. 这边的FactoryBean,Spring设计用于新建复杂bean的,联想下GOF设计模式的创建型,一样的为了解决复杂的bean实例化过程. 其实这边的FactoryBean就是一个factory method[gof定义的意图:定义一个用于创建对象的接口,让子类决定实例化哪个类.Factory Method使一个类的实例化延迟到其子类]. 这边的处理主要涉及3个方法,我们来看看3个方法各自的职责: getObjectForBeanInstance: 参数校验之类的准备工作 getObjectFromFactoryBean: 单例时,确保实例是全局唯一的 doGetObjectFromFactoryBean: 实实在在的实例化 参数校验之类的准备工作 AbstractBeanFactory的getObjectForBeanInstance处理. 如果name制定要获取FactoryBean本身实例,而beanInstance却又不是FactoryBean,直接抛异常 如果不需要调用getObject实例化,直接返回实例 尝试从缓存中获取实例[FactoryBeanRegistrySupport负责] 准备beanDefinition,委托getObjectFromFactoryBean处理 单例时保障实例全局唯一 FactoryBeanRegistrySupport的getObjectFromFactoryBean处理 FactoryBeanRegistrySupport负责FactoryBean相关的操作,并缓存FactoryBean的getObject实例化的bean. 判断factory是单例,同时已经new好了(后面需要调用getObject获取目标对象,这边需要factory已经实例化) 单例时,先尝试去缓存找;如果找不到或者不是单例,委托doGetObjectFromFactoryBean实例化一个 由于这样新建就没有机会调用BeanPostProcessor了,所以这边直接调用其postProcessAfterInitialization[职责职责职责,AbstractAutowireCapableBeanFactory干的] 缓冲得到的实例 实例化,干活的 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; } (编辑:云计算网_泰州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |