Spring源码分析系列——bean创建过程分析(三)——工厂方法创建bean

前言

spring创建bean的方式

  1. 构造方法

    1. 无参构造方法
    2. 有参构造方法
  2. 工厂方法

    1. 静态工厂方法
    2. 实例工厂方法
  3. 实现FactoryBean接口

    前两篇《Spring源码分析系列——bean创建过程分析(一)——默认无参构造方法创建bean》《Spring源码分析系列——bean创建过程分析(二)——有参构造方法创建bean》介绍了构造方法创建bean的主要流程,本篇分析一下工厂方式创建bean,包括静态工厂和实例工厂方式

测试代码准备

xml配置如下

<bean id="boyService" class="edu.dongnao.courseware.spring.instantiate.InstantiateFactory" 
		factory-method="getBoyFromStaticFactoryMethod" >
		<!--<property name="friend" ref="grilService"></property>-->
</bean>
<bean id="instantiateFactory" class="edu.dongnao.courseware.spring.instantiate.InstantiateFactory" />

实体类代码

public class Lad implements Boy {
    private String name;
    private Gril friend;
    private Money money;
    
    public Lad(String name) {
        this.name = name;
    }
}


public class MagicGril implements Gril {
    private String name;
    private Boy friend;
    public MagicGril(){}
    public MagicGril(String name) {
        this.name = name;
    }
}

工厂方法代码

public class InstantiateFactory {

	public static Lad getBoyFromStaticFactoryMethod() {
		return new Lad("swk");
	}

	public MagicGril getGrilFromMemberFactoryMethod(String name) {
		return new MagicGril(name);
	}
}

运行测试代码

public class MyXmlConfig {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("/application.xml");
        Lad lad = (Lad) ac.getBean("boyService");
        System.out.println(lad);
    }
}

createBeanInstance()方法分析

基于之前的分析,创建单例bean的步骤都是经getBean、doGetBean、createBean、doCreateBean、createBeanInstance等步骤,本次直接从createBeanInstance方法开始分析

代码精简后

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}
}

很直观的,如果bean定义中有factoryMethodName,则直接走工厂方式创建bean。

instantiateUsingFactoryMethod()方法分析

protected BeanWrapper instantiateUsingFactoryMethod(
			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

		return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
	}

跟有参构造方法创建的autowireConstructor()方法一样,都是委托给ConstructorResolver类处理,看一下它的instantiateUsingFactoryMethod()方法。
精简之后

public BeanWrapper instantiateUsingFactoryMethod(
			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);

		Object factoryBean;
		Class<?> factoryClass;
		boolean isStatic;
		
		//工厂bean名称
		String factoryBeanName = mbd.getFactoryBeanName();
		//如果有工厂bean,则走实例工厂创建,没有则走静态工厂创建
		if (factoryBeanName != null) {
			if (factoryBeanName.equals(beanName)) {
				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
						"factory-bean reference points back to the same bean definition");
			}
			//从bean工厂中获取factoryBean实例
			factoryBean = this.beanFactory.getBean(factoryBeanName);
			if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
				throw new ImplicitlyAppearedSingletonException();
			}
			factoryClass = factoryBean.getClass();
			isStatic = false;
		}
		//如果有工厂bean,则走实例工厂创建,没有则走静态工厂创建
		else {
			// It's a static factory method on the bean class.
			if (!mbd.hasBeanClass()) {
				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
						"bean definition declares neither a bean class nor a factory-bean reference");
			}
			factoryBean = null;
			factoryClass = mbd.getBeanClass();
			isStatic = true;
		}

		Method factoryMethodToUse = null;
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;

		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			Object[] argsToResolve = null;
			//从缓存中找,第一次没有
			synchronized (mbd.constructorArgumentLock) {
				factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
				if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached factory method...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
			}
		}
		
		//决定是用哪个静态方法
		if (factoryMethodToUse == null || argsToUse == null) {
			// Need to determine the factory method...
			// Try all methods with this name to see if they match the given arguments.
			factoryClass = ClassUtils.getUserClass(factoryClass);

			List<Method> candidates = null;			
			if (candidates == null) {
				candidates = new ArrayList<>();
				//找到工厂类所有的方法
				Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
				for (Method candidate : rawCandidates) {
				//找到静态的,并且是定义的工厂方法名的方法
					if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
						candidates.add(candidate);
					}
				}
			}
			
			//如果只有一个符合的静态方法,并且没有指定构造方法参数
			if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
				Method uniqueCandidate = candidates.get(0);
				//方法的形参数为0,则直接用反射创建
				if (uniqueCandidate.getParameterCount() == 0) {
					mbd.factoryMethodToIntrospect = uniqueCandidate;
					synchronized (mbd.constructorArgumentLock) {
						//放入缓存
						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
						mbd.constructorArgumentsResolved = true;
						mbd.resolvedConstructorArguments = EMPTY_ARGS;
					}
					bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
					return bw;
				}
			}
			
			//如果有多个候选方法,则需要排序
			if (candidates.size() > 1) {  // explicitly skip immutable singletonList
				candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
			}

			ConstructorArgumentValues resolvedValues = null;
			boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Method> ambiguousFactoryMethods = null;

			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				//解析bean定义中定义的构造方法参数
				if (mbd.hasConstructorArgumentValues()) {
					ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
					resolvedValues = new ConstructorArgumentValues();
					minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
				}
				else {
					minNrOfArgs = 0;
				}
			}

			LinkedList<UnsatisfiedDependencyException> causes = null;

			for (Method candidate : candidates) {
				int parameterCount = candidate.getParameterCount();

				if (parameterCount >= minNrOfArgs) {
					ArgumentsHolder argsHolder;

					Class<?>[] paramTypes = candidate.getParameterTypes();
					if (explicitArgs != null) {
						// Explicit arguments given -> arguments length must match exactly.
						if (paramTypes.length != explicitArgs.length) {
							continue;
						}
						argsHolder = new ArgumentsHolder(explicitArgs);
					}
					else {
						// Resolved constructor arguments: type conversion and/or autowiring necessary.
						try {
							String[] paramNames = null;
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								paramNames = pnd.getParameterNames(candidate);
							}
							//根据bean定义的参数,转换给工厂方法需要的参数
							argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
									paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
						}
						catch (UnsatisfiedDependencyException ex) {
							
						}
					}

					int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
							argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
					
					if (typeDiffWeight < minTypeDiffWeight) {
						factoryMethodToUse = candidate;
						argsHolderToUse = argsHolder;
						argsToUse = argsHolder.arguments;
						minTypeDiffWeight = typeDiffWeight;
						ambiguousFactoryMethods = null;
					}
					
					
				}
			}

			
			
			if (explicitArgs == null && argsHolderToUse != null) {
				mbd.factoryMethodToIntrospect = factoryMethodToUse;
				//将第一次找到的方法、及参数放入缓存,以备下次查找时直接从缓存中取
				argsHolderToUse.storeCache(mbd, factoryMethodToUse);
			}
		}
		
		//根据指定的工厂bean和指定的工厂方法或者找到的静态工厂方法创建bean
		bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
		return bw;

总结

工厂方法创建bean与构造方法创建bean大致步骤差不多,都是先确定方法和参数,然后反射创建bean。

上一篇:spring 5.0.21.BUILD-SNAPSHOT源码解读,第二集(Spring循环依赖解决方案)


下一篇:谈谈你对SpringIOC的理解