Spring 5.x 源码之旅十八getBean详解四

instantiateUsingFactoryMethod工厂方法实例化

上次讲实例提供器,讲了一篇,这次继续后面的,工厂方法实例化,比如bean注解的也算。
先要获取构造器解析器,然后用工厂方法进行实例化。

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

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

ConstructorResolver

里面没啥逻辑,主要是保存beanFactory

	public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
		this.beanFactory = beanFactory;
		this.logger = beanFactory.getLogger();
	}

instantiateUsingFactoryMethod真正创建的方法-分段1

这个方法很核心,他会根据工厂方法的是不是唯一来进行创建,如果唯一,就直接创建,不唯一的话还要进行所有方法获取,然后选出工厂方法,再处理,我们先讲简单的情况吧。先说第一段,先创建一个实例持有器,其实就是个包装类,然后从RootBeanDefinition中获取factoryBeanName,也就工厂方法,比如说bean注解的方法就是,如果存在判断下是不是要创建自身,会报错,创建自身等于无限循环创建了。如果不是的话就获取factoryBean即工厂实例,获取工厂类型,设置非静态的。如果获取不到工厂实例,说明是静态方法。

		BeanWrapperImpl bw = new BeanWrapperImpl();//实例持有器
		this.beanFactory.initBeanWrapper(bw);

		Object factoryBean;//工厂实例
		Class<?> factoryClass;//工厂类型
		boolean isStatic;//是否是静态的,存在factoryBeanName表示是实例工厂,非静态方法,否则是静态的
		//factoryBeanName,也就是工厂方法所属的类的简单名字,比如配置类,这里的factoryBean,不是FactoryBean接口
		String factoryBeanName = mbd.getFactoryBeanName();
		if (factoryBeanName != null) {//存在factoryBean
			if (factoryBeanName.equals(beanName)) {//factoryBean创建出来的是工厂自身,会报异常,这样貌似等于无限递归创建了
				throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
						"factory-bean reference points back to the same bean definition");
			}
			factoryBean = this.beanFactory.getBean(factoryBeanName);//获得factoryBean
			if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {//已经创建了
				throw new ImplicitlyAppearedSingletonException();
			}
			factoryClass = factoryBean.getClass();
			isStatic = false;//非静态的
		}
		else {//静态的方法,无factoryBean实例
			// 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;
		}

instantiateUsingFactoryMethod真正创建的方法-分段2

准备好参数,尝试获取已经解析的数据,第一次都是空的。

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

instantiateUsingFactoryMethod真正创建的方法-分段3

如果没解析过,就获取factoryClass的用户定义类型,因为此时factoryClass可能是CGLIB动态代理类型,所以要获取用父类的类型。如果工厂方法是唯一的,就是没重载的,就获取解析的工厂方法,如果不为空,就添加到一个不可变列表里,如果为空的话,就要去找出factoryClass的以及父类的所有的方法进一步找出方法修饰符一致且名字跟工厂方法名字相同的且是bean注解的方法,并放入列表里。

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> candidateList = null;
			if (mbd.isFactoryMethodUnique) {//如果工厂方法唯一,没重载的
				if (factoryMethodToUse == null) {
					factoryMethodToUse = mbd.getResolvedFactoryMethod();//获取解析的工厂方法
				}
				if (factoryMethodToUse != null) {//存在的话,返回仅包含factoryMethodToUse的不可变列表
					candidateList = Collections.singletonList(factoryMethodToUse);
				}
			}
			if (candidateList == null) {//如果没找到工厂方法,可能有重载
				candidateList = new ArrayList<>();
				Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);//获取factoryClass以及父类的所有方法作为候选的方法
				for (Method candidate : rawCandidates) {//过滤出修饰符一样,工厂方法名一样且是bean注解的方法
					if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
						candidateList.add(candidate);//如果isStatic修饰符一样且名字跟工厂方法名一样就添加
					}
				}
			}

ClassUtils.getUserClass找出用户定义的类型

public static Class<?> getUserClass(Class<?> clazz) {
		if (clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {//如果包含CGLIB的名字符号,尝试获取父类
			Class<?> superclass = clazz.getSuperclass();
			if (superclass != null && superclass != Object.class) {
				return superclass;
			}
		}
		return clazz;
	}

getCandidateMethods获取所有候选方法包括父类的

	private Method[] getCandidateMethods(Class<?> factoryClass, RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			return AccessController.doPrivileged((PrivilegedAction<Method[]>) () ->
					(mbd.isNonPublicAccessAllowed() ?
						ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods()));
		}
		else {
			return (mbd.isNonPublicAccessAllowed() ?
					ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
		}
	}

ReflectionUtils.getAllDeclaredMethods用反射获取方法

如果允许非Public的方法,就获取所有申明的方法,包括父类的,否则就是Public的方法,包括父类的,默认是允许的,我们直接看允许的就可以,原理一样的。

	public static Method[] getAllDeclaredMethods(Class<?> leafClass) {
		final List<Method> methods = new ArrayList<>(32);
		doWithMethods(leafClass, methods::add);
		return methods.toArray(EMPTY_METHOD_ARRAY);
	}
	public static void doWithMethods(Class<?> clazz, MethodCallback mc) {
		doWithMethods(clazz, mc, null);
	}
doWithMethods递归获取

递归获取所有的方法以及父类的,获取后执行mc.doWith(method)方法,其实就是上面的methods::add把方法添加到列表里,最后转换成数组返回。

public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {
		// Keep backing up the inheritance hierarchy.
		Method[] methods = getDeclaredMethods(clazz, false);
		for (Method method : methods) {
			if (mf != null && !mf.matches(method)) {
				continue;
			}
			try {
				mc.doWith(method);
			}
			catch (IllegalAccessException ex) {
				throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
			}
		}
		if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) {
			doWithMethods(clazz.getSuperclass(), mc, mf);
		}
		else if (clazz.isInterface()) {
			for (Class<?> superIfc : clazz.getInterfaces()) {
				doWithMethods(superIfc, mc, mf);
			}
		}
	}

剩下的下次讲吧。

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

发布了235 篇原创文章 · 获赞 74 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/wangwei19871103/article/details/105052088