2023-09-16
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105036970

isFactoryBean(String name)根据名字判断是否是FactoryBean

我们继续上篇,上篇讲了getMergedLocalBeanDefinition,以及为什么要用这个,本篇来讲后面的isFactoryBean方法,怎么来判断一个beanName是否是FactoryBean类型。getBean比较复杂,后面一起讲,暂时知道这个可以获取对象就好,本篇讲这部分:

202309162312041411.png

    @Override
    	public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
    		String beanName = transformedBeanName(name);//获取转换后的名字
    		Object beanInstance = getSingleton(beanName, false);
    		if (beanInstance != null) {//如果已经是单例了,就判断是否是FactoryBean类型
    			return (beanInstance instanceof FactoryBean);
    		}
    		// 没有单例,看是否有bean定义,没有就看父类bean工厂
    		if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {			
    			return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
    		}
    		return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
    	}

transformedBeanName转换后的名字

我们来看这个转换名字,其实跟上篇说的FactoryBean名字相关,我们还是来看源码吧:

    	protected String transformedBeanName(String name) {
    		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
    	}

BeanFactoryUtils的transformedBeanName

首先判断是不是有&前缀,没有就直接返回,说明不是FactoryBean的名字,否则就从缓存里获取,然后把前缀&去掉返回。

    public static String transformedBeanName(String name) {
    		Assert.notNull(name, "'name' must not be null");
    		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
    			return name;
    		}
    		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
    			do {
    				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
    			}
    			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
    			return beanName;
    		});
    	}

canonicalName取出原始名字

进行名字的规范化,其实就是取出原始名字,如果是别名就从映射中取原始名,是原始名字直接返回。

    public String canonicalName(String name) {
    		String canonicalName = name;
    		// Handle aliasing...
    		String resolvedName;
    		do {
    			resolvedName = this.aliasMap.get(canonicalName);
    			if (resolvedName != null) {
    				canonicalName = resolvedName;
    			}
    		}
    		while (resolvedName != null);
    		return canonicalName;
    	}

getSingleton(String beanName, boolean allowEarlyReference)获取单例

这个方法传入一个名字和是否允许早期引用,这个是为了解决循环依赖的问题,这个后面会讲,现在忽略就行。singletonObjects是一个ConcurrentHashMap,放已经创建好的单例,如果发现有创建好了,就直接返回,否则判断是否正在创建isSingletonCurrentlyInCreationearlySingletonObjectsHashMap,用来保存运行早期创建引用的单例,为了解决循环依赖。我们可能会奇怪,为什么earlySingletonObjects不是ConcurrentHashMap,其实因为他所有的操作,都是在synchronized 同步块中了,所以不需要了,而singletonObjects则可以在没有同步块的地方使用。继续说,如果在earlySingletonObjects也没找到,又是允许早期引用的,就从单例singletonFactories工厂中获取一个工厂,其实就是一个可以获取对象的工厂,只要存在,就能通过getObject()获取,然后放进earlySingletonObjects,删除工厂,其实有循环引用的时候就可以派上用了,后面会说。

    @Nullable
    	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    		Object singletonObject = this.singletonObjects.get(beanName);
    		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    			synchronized (this.singletonObjects) {
    				singletonObject = this.earlySingletonObjects.get(beanName);
    				if (singletonObject == null && allowEarlyReference) {
    					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    					if (singletonFactory != null) {
    						singletonObject = singletonFactory.getObject();
    						this.earlySingletonObjects.put(beanName, singletonObject);
    						this.singletonFactories.remove(beanName);
    					}
    				}
    			}
    		}
    		return singletonObject;
    	}

isSingletonCurrentlyInCreation是否正在创建中

singletonsCurrentlyInCreation这个是个set存放正在创建的单例的名字,所以可以判断是否正在创建中。

    	public boolean isSingletonCurrentlyInCreation(String beanName) {
    		return this.singletonsCurrentlyInCreation.contains(beanName);
    	}

isFactoryBean(String beanName, RootBeanDefinition mbd)根据名字和bean定义判断是否是FactoryBean

如果FactoryBean单例没获取到,此时只能通过名字和bean定义看是否是FactoryBean了。如果定义本身定义了isFactoryBean,那就直接返回结果,否则需要进行类型预测,他会进行反射,看看名字对应的类是否是FactoryBean类型的,如果预测出来的类型是FactoryBean,那就返回true了,否则就false

    protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
    		Boolean result = mbd.isFactoryBean;
    		if (result == null) {
    			Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
    			result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
    			mbd.isFactoryBean = result;
    		}
    		return result;
    	}

获取FactoryBean

如果发现名字是FactoryBean类型的话,就会在名字前加前缀&,然后去获取,获取完了判断是否是FactoryBean类型,是的话再判断是否需要理解创建FactoryBean中的对象,如果是的话就直接获取名字,此时的名字是没有&前缀的,也就直接获取FactoryBeangetObject()方法创建的对象。当然如果名字不是FactoryBean类型的话,就直接获取对象。

202309162312046812.png

总结

这部分主要就是创建单例,如果发现是FactoryBean类型的话,就获取FactoryBean,然后判断是否需要立即进行getObject()方法创建的对象,需要的话就创建。如果不是FactoryBean类型的话,就直接获取创建对象。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

阅读全文