봄 5.x를 소스 여행 아홉 다섯 개의 getBean 상세한

만 인수가없는 팩토리 메소드

매개 변수가있는 경우 하나의 생성자 경우, 직접 빈 정의 속성을 설정하지 않을 경우 다음 포장에 개체 집합의 인스턴스를 참조하십시오.

//如果只获取到一个方法,且传入的参数为空,且没有设置构造方法参数值
			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)생성자 차이의 두 가지 유형이 내가 사용하는 내용이 무엇인지 알 수 없도록,이 이상이보고됩니다 동일합니다. 있다 minNrOfArgs매개 변수의 최소 번호가 존재하는 경우, 최적화를 위해 사용되는, 또한 키 적은 다음, 판사로 이동 건너 뛰거나 심지어 경기에하지 수행 할 필요가 없습니다 매개 변수의 최소 수보다 몇 수 있지만, 자원의 낭비. 경우 minNrOfArgs이며 0, 그 다음 당신이 결정하기 위해 하나 하나를 백업해야, 숫자 매개 변수에 한계가 없음을 보여주는 작은 차이와 라인에서 가장.

			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