봄 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);
}
}
}
간단한 예와 함께 다시는이 과정을 분석합니다.
음, 오늘, 우리는 단지 자신의 학습, 제한 용량 이해를 참조하십시오 위대한 하나님을 뿌리지 마십시오 도움이 연구에 희망과 이해, 용서하십시오.