春5.xのソースの旅19詳細5 getBean

唯一の引数なしのファクトリメソッド

パラメータがある場合のみ、1つのコンストラクタ場合は、直接豆定義されたプロパティを設定していない場合は、パッケージにオブジェクトのセットをインスタンス化し、参照してください。

//如果只获取到一个方法,且传入的参数为空,且没有设置构造方法参数值
			if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
				Method uniqueCandidate = candidateList.get(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;
				}
			}

インスタンス化インスタンス化するファクトリメソッド

これは、インスタンス化するパラメータファクトリメソッドの最も単純です。

private Object instantiate(String beanName, RootBeanDefinition mbd,
			@Nullable Object factoryBean, Method factoryMethod, Object[] args) {

		try {
			if (System.getSecurityManager() != null) {
				return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						this.beanFactory.getInstantiationStrategy().instantiate(
								mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
						this.beanFactory.getAccessControlContext());
			}
			else {//获取实例化策略进行实例化
				return this.beanFactory.getInstantiationStrategy().instantiate(
						mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean instantiation via factory method failed", ex);
		}
	}

SimpleInstantiationStrategy的インスタンス化

実際には、戦略の既定のインスタンスがCglibSubclassingInstantiationStrategy使用できるということであるCGLIBダイナミックプロキシを作ることが、唯一の注入法の形で、これは言及または親が存在しないファクトリメソッドを呼び出すSimpleInstantiationStrategy実装を。実際には、ファクトリ・インスタンスファクトリメソッド呼び出し、パラメータを渡したが、パラメータは、空の配列であるEMPTY_ARGS、オブジェクトを返します。

@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Object factoryBean, final Method factoryMethod, Object... args) {

		try {
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					ReflectionUtils.makeAccessible(factoryMethod);
					return null;
				});
			}
			else {//设置factoryMethod可访问
				ReflectionUtils.makeAccessible(factoryMethod);
			}
			//获取前面存在的线程本地的FactoryMethod
			Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
			try {
				currentlyInvokedFactoryMethod.set(factoryMethod);//设置新的
				Object result = factoryMethod.invoke(factoryBean, args);//调用工厂方法
				if (result == null) {
					result = new NullBean();
				}
				return result;
			}
			finally {
				if (priorInvokedFactoryMethod != null) {//如果线程本地存在,就设置回老的
					currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
				}
				else {//否则就删除,等于没设置
					currentlyInvokedFactoryMethod.remove();
				}
			}
		}
		...
	}

複数のパラメータがありますファクトリメソッド(集中)

次は古典的な場所である、ファクトリメソッドの複数のパラメータに対処するためにどのように、それが呼ばれるべきれる一端、インチ

セグメントの並べ替えの1-

最初のファクトリメソッドの特定の規則に従ってソートされ、ルールがする修飾押しpublic優先行を、次いで改質パラメータ同じ行数を押します

Method[] candidates = candidateList.toArray(new Method[0]);
AutowireUtils.sortFactoryMethods(candidates);//排序,根据public优先,参数多的优先

例えば、私が持っている6、同じ名前が、実際には、異なる修飾子をオーバーロードされたパラメータの数が異なる、何の事前ソート:
ここに画像を挿入説明
ソート:ありません
ここに画像を挿入説明

ソートsortFactoryMethodsのAutowireUtils

	public static void sortFactoryMethods(Method[] factoryMethods) {
		Arrays.sort(factoryMethods, EXECUTABLE_COMPARATOR);
	}

EXECUTABLE_COMPARATORコンパレータ

	//先比较修饰符,再比较参数个数 从Public到非Public,参数从多到少
	private static final Comparator<Executable> EXECUTABLE_COMPARATOR = (e1, e2) -> {
		int result = Boolean.compare(Modifier.isPublic(e2.getModifiers()), Modifier.isPublic(e1.getModifiers()));
		return result != 0 ? result : Integer.compare(e2.getParameterCount(), e1.getParameterCount());
	};

準備セグメント2-

ファクトリメソッドは、設定パラメータ値(合格した場合)へのアクセスなど、いくつかの処理ので、パラメータを解析し続け、その後、自動組立モードを取得しているため、工場出荷時の一般的な方法はAUTOWIRE_CONSTRUCTOR、定義するminTypeDiffWeight、差分値を複数のファクトリメソッドがある場合、これが使用される場合、組立工場の特定のパラメータおよび方法を参照bean最小方差分タイプを、。また、定義されたあるambiguousFactoryMethods方法は、差分値を格納するために使用されるように、同じタイプが説明され、インスタンス化するファクトリメソッドを伝えることができませんでしたが。例えば、protected UserDao userDao(TestBean2 t2)およびpublic UserDao userDao(TestBean t1)コンストラクタ差の2種類が、私が使用するかわからないので、それが異常に報告されますが、同じです。あるminNrOfArgsパラメータの最小数は、存在する場合、最適化のために使用され、また、キーの少ないし、裁判官に行くスキップ、あるいは試合得ることはありませんする必要はありませんパラメータの最小数よりも、いくつかの数が、資源の無駄。場合minNrOfArgs0、それはあなたが決定するために一つ一つをバックアップする必要があり、番号パラメータに制限がないことを示している最小の違いやラインの中で最も。

			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 {
				if (mbd.hasConstructorArgumentValues()) {//如果存在构造器参数值,就解析出最小参数个数
					ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
					resolvedValues = new ConstructorArgumentValues();
					minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
				}
				else {
					minNrOfArgs = 0;//没有就为0
				}
			}

3-セグメントコア作業

このコアは、内部の自動組立は、まず、すでにからフィルタリングされているcandidates場合、あなたは選択ルールを持っている必要がありますので、インスタンス化するために、選択する最初のすべてのパラメータの数が最小値より小さくすることはできませんどちらのファクトリメソッドが、我々は知りませんそこのパラメータは、表示された矛盾の数が存在すると、その後、あなたが検出の各ファクトリメソッドの名前にパラメータ検出器パラメータの名前を得ることはありませんし、その後保持装置のパラメータを作成し、カスタムアセンブリ、依存が関与しますパラメータがインスタンス化。最後に、方法およびプラントパラメータタイプパラメータ保持部、その差の格納された最小値、あいまいなセット空集合と比較します。工場でのデータの収集がある場合は、コレクションの値に同じ差異がある場合は、例外が報告されますインスタンス化するために、どの方法を知りません。大雑把に多くのことを必要とするが、ゆっくりとしか解析し、そのようなプロセス、上。

//遍历每个后选的方法,查看可以获取实例的匹配度
			for (Method candidate : candidates) {
				Class<?>[] paramTypes = candidate.getParameterTypes();
				if (paramTypes.length >= minNrOfArgs) {
					ArgumentsHolder argsHolder;

					if (explicitArgs != null) {//显示参数存在,如果长度不对就继续下一个,否则就创建参数持有其持有

						if (paramTypes.length != explicitArgs.length) {
							continue;
						}
						argsHolder = new ArgumentsHolder(explicitArgs);
					}
					else {

						try {
							String[] paramNames = null;
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();//获取参数名字探测器
							if (pnd != null) {//存在的话进行探测
								paramNames = pnd.getParameterNames(candidate);
							}
							argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
									paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
						}
						catch (UnsatisfiedDependencyException ex) {
							...
							continue;
						}
					}
					//根据参数类型匹配,获取类型的差异值
					int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
							argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
					// Choose this factory method if it represents the closest match.
					if (typeDiffWeight < minTypeDiffWeight) {//保存最小的,说明参数类型相近
						factoryMethodToUse = candidate;
						argsHolderToUse = argsHolder;
						argsToUse = argsHolder.arguments;
						minTypeDiffWeight = typeDiffWeight;
						ambiguousFactoryMethods = null;//没有模棱两可的方法
					}//如果出现类型差异相同,参数个数也相同的,而且需要严格判断,参数长度也一样,常数类型也一样,就可能会无法判定要实例化哪个,就会报异常

					else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
							!mbd.isLenientConstructorResolution() &&
							paramTypes.length == factoryMethodToUse.getParameterCount() &&
							!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
						if (ambiguousFactoryMethods == null) {
							ambiguousFactoryMethods = new LinkedHashSet<>();
							ambiguousFactoryMethods.add(factoryMethodToUse);
						}
						ambiguousFactoryMethods.add(candidate);
					}
				}
			}

このプロセスを分析するための簡単な例でバック。

さて、今日ここに、私たちは自分自身の学習、限られた容量を理解し、偉大な神は見スプレーしないで、言い訳してください、助けの調査に希望と理解しています。

公開された235元の記事 ウォン称賛74 ビュー30000 +

おすすめ

転載: blog.csdn.net/wangwei19871103/article/details/105081731