Interpretation of Spring 5.x source Tour fourteen isFactoryBean method

isFactoryBean (String name) to determine whether the name is based on FactoryBean

We continue to Part I, Part I talked about getMergedLocalBeanDefinition, and why should this, in terms of the latter Benpian isFactoryBeanmethods, how to judge a beanNamewhether it is FactoryBeantype. getBeanMore complex, talk back together temporarily to know that you can get an object like herein, this talk about this part:
Here Insert Picture Description

@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));
	}

After conversion the name of transformedBeanName

We look at this conversion name, in fact, to keep up with papers say FactoryBeanthe name of the relevant, we look at the source of it:

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

BeanFactoryUtils的transformedBeanName

First, judgment is not a &prefix, there is no direct return, indicating not FactoryBeanname, otherwise they are taken from the cache, and then the prefix &removed to return.

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 remove the original name

Standardization for name, in fact, remove the original name, if the original name is an alias he took from the map, it is the original name of the direct return.

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) Example acquisition unit

This method is passed a name and whether to allow early references, this is a circular dependency in order to solve the problem, this will speak later, now on the line is ignored. singletonObjectsIs a ConcurrentHashMap, put already created a single case, if found to have created, direct return, or to determine whether you are creating isSingletonCurrentlyInCreation, earlySingletonObjectsis HashMapused to create a single case cited save the run early, in order to resolve circular dependencies. We may wonder why earlySingletonObjectsnot ConcurrentHashMap, in fact, because of all his operations are in synchronizedsync block, so do not need, and singletonObjectscan be used where there is no sync block. Went on to say that if earlySingletonObjectsdid not find, but also allow early referenced from singleton to singletonFactoriesget a factory plant, in fact, can obtain a factory object, as long as there is, we can through getObject()acquisition, and then into earlySingletonObjects, delete the factory, in fact, there are circular references when you can put to use, it goes on to say.

@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;
	}

Are isSingletonCurrentlyInCreation being created

singletonsCurrentlyInCreationThis is the name of a single case set storage being created, it can be judged whether being created.

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

isFactoryBean (String beanName, RootBeanDefinition mbd) The name and determines whether the bean definition FactoryBean

If FactoryBeansingleton did not get to this time only by name and beandefine whether it is to see FactoryBeanthe. If the definition itself is defined isFactoryBean, it returns the result directly, or need to be the type of prediction, he will reflect, to see if the name of the corresponding class is the FactoryBeantype if the type is predicted FactoryBean, then returned true, and otherwise 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;
	}

Get FactoryBean

If you find the name of FactoryBeanthe type, you would add the prefix before the name &, then go get, get over to determine whether FactoryBean type, that is the case then determine whether you need to understand to create FactoryBeanobjects, and if so directly obtain the name, this time name is no & prefix, also direct access to FactoryBeanthe getObject()object method creates. Of course, if the name is not a FactoryBeantype, then it direct access to the object.
Here Insert Picture Description

to sum up

This part is to create a single case, if found to be FactoryBeantype, then get FactoryBean, and then determine whether you need immediate getObject()object methods created, if required, will be created. If this is not FactoryBeanthe type, then it direct access to create objects.

Well, here today, we hope to help study and understand, do not spray the Great God see, understand only their own learning, limited capacity, please excuse.

Published 235 original articles · won praise 74 · views 30000 +

Guess you like

Origin blog.csdn.net/wangwei19871103/article/details/105036970