剑指spring源码(四)

spring 专栏收录该内容
19 篇文章 1 订阅

剑指spring源码(四)

前言

距离上一篇spring源码系列文章已经三个月了,这段时间有点懒,更新频率大大下降了,甚至几度想要放弃这个系列,因为感觉真的不是我能掌控的,spring太精妙了,经过前面几篇博客的铺垫,我们这篇来聊一聊getBean时期spring都干了什么,都有哪几个后置处理器,都是干嘛的,还有循环引用的问题,以及什么情况的循环引用可以解决

ioc

refresh->
finishBeanFactoryInitialization(beanFactory);->
beanFactory.preInstantiateSingletons();->
getBean(beanName);->
doGetBean()

doGetBean关键代码如下

	//singletonObjects->earlySingletonObjects->singletonFactories
	//三级缓存获取bean
	Object sharedInstance = getSingleton(beanName);
	
	//创建bean生命周期
	if (mbd.isSingleton()) {
		sharedInstance = getSingleton(beanName, () -> {
		return createBean(beanName, mbd, args);
		});
	}

第一个getSingleton代码如下:三级缓存主要作用是解决循环引用

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//单例池中拿 第一级缓存
		Object singletonObject = this.singletonObjects.get(beanName);
		//单例池没有
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//锁住单例池
			synchronized (this.singletonObjects) {
				//early中拿 第三级缓存
				singletonObject = this.earlySingletonObjects.get(beanName);
				//第级三缓存拿不到
				if (singletonObject == null && allowEarlyReference) {
					//singletonFactories拿 ,第二级缓存
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						//第级二缓存拿到了
						singletonObject = singletonFactory.getObject();
						//put到第三级缓存
						this.earlySingletonObjects.put(beanName, singletonObject);
						//移除二级缓存
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

第二个getSingleton会回调createBean方法,createBean关键代码如下

第一次执行后置处理器-aop切面aspect

			
			//InstantiationAwareBeanPostProcessor
			// postProcessBeforeInstantiation 实例化前(实例化范围大,从第一次执行后置处理器就执行了,贯穿8次后置处理器)
			//postProcessAfterInitialization  初始化后(初始化范围小,第七次执行后置处理器回调了BeforeInitialization)
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		
		//resolveBeforeInstantiation代码如下
		protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
				//遍历所有的InstantiationAwareBeanPostProcessor执行postProcessBeforeInstantiation方法,
				//第一次执行后置处理器 这个后置处理器99.9%返回null,除非我们覆盖postProcessBeforeInstantiation
				//aop相关 核心缓存切面信息,把切面myAspect标志为不能代理状态 ,如果没有aop可以忽略这一次的后置处理器
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					//这里如果bean不空,则会继续执行一次postProcessAfterInitialization方法
					//为什么要执行这个,因为这是spring的规则,初始化后就得执行这个方法
					//但是为什么spring不设计成执行postProcessAfterInstantiation方法呢?
					//因为postProcessAfterInstantiation方法返回true代表后续会进行DI填充,
					//而如果此时返回了bean不为null,后续根本就不会DI,所以没有意义
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}
//第一次后置处理器调用 目的是 this.advisedBeans.put(cacheKey, Boolean.FALSE);这一行代码 即把切面aspect标为不需要代理的状态
	//如果自己代理自己会发生很毁灭性的事情,无限递归stackOverFlow
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		//beanName不为null和""的时候cacheKey = beanName(factoryBean的情况要加&) 否则cacheKey=beanClass
		// TODO  beanName什么情况是null???
		Object cacheKey = getCacheKey(beanClass, beanName);
		//beanName不为null和"" 或者 targetSourcedBeans没有beanName(后者几乎都是true)
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			//advisedBeans---Map<Object, Boolean>
			//Object是缓存key(beanName),false代表此bean不要进行代理
			// (这里不要代理有三个意思,一个是不要代理,一个是不能代理(Aspect),还一个是已经被代理(appConfig))
			// true代表要进行代理

			//advisedBeans已经有此beanName了,直接return null
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			//advice/pointcut/advisor/aspect都是InfrastructureClass ,都不要被代理
			//shouldSkip 缓存myAspect切面信息
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				//不要代理此beanName对应的bean  
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		//TODO 这段代码片几乎没有调用到,除非自定义TargetSource???
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}

下面以一个例子说明第一个后置处理器的作用以及spring的设计原理

@Component
public class IABeanPostProcessor  implements InstantiationAwareBeanPostProcessor {

	//bean的产生:
	// 空对象,第一次后置处理器,
	// 第二次:决策构造器,
	// 第三次:merge,
	// 第四次:添加到单例池,提前暴露空对象
	//第五次:实例化后的后置处理器,bean是否需要完成属性填充
	//第六次:属性填充
	//第七八次:初始化前后的后置处理器
	//第九次:销毁
	//初始化范围小,在属性填充后执行
	//初始化前   第七次执行后置处理器回调


	//实例化 范围更大 贯穿9次后置处理器中
	//实例化前  第一次执行后置处理器resolveBeforeInstantiation 会从这里返回  但是结束时还要回调postProcessAfterInitialization
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		return "Instant before";
	}

	//初始化后  第八次执行后置处理器回调,
	//第一次执行后置处理器回调(需要postProcessBeforeInstantiation返回不为null)
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return "init after";
	}

	//第五次执行后置处理器
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		return true; //bean需要完成属性填充
	}

}


	public static void main(String[] args) {
		AnnotationConfigApplicationContext app =
				new AnnotationConfigApplicationContext(AppConfig.class);
		System.out.println("ioc容器创建完毕");
		Object userService = app.getBean("userService");
		//第一次后置处理器执行IABeanPostProcessor的postProcessBeforeInstantiation,返回bean不为null
		//再执行postProcessAfterInitialization,所以下面输出init after
		//当你把 postProcessAfterInitialization注释掉,返回的就是Instant before
		System.out.println(userService);
	}

第二次执行后置处理-推断构造器

第二次执行后置处理器是决策构造器,入口为AbstractAutowireCapableBeanFactory的doCreateBean方法的
instanceWrapper = createBeanInstance(beanName, mbd, args);这行代码
我们来看看createBeanInstance这个方法干了什么
我注意到这段代码作用·是提高原型bean的创建速率,不再需要每次都去推断构造器

		// 为重复创建原型bean提供快捷方式
		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		//一般args==null
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				//第一次resolvedConstructorOrFactoryMethod为null,
				//第二次进if
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		//第一次不进if
		//第二次进if
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				//第二次进这里,不再需要推断构造器了
				return instantiateBean(beanName, mbd);
			}
		}
		//后续代码决策构造器,构造对象后给mbd.resolvedConstructorOrFactoryMethod赋值(createBeanInstance最后一行代码赋的值)

下面这行代码就是第二次后置处理器,推断构造器,循环遍历beanPostProcessor,执行determineCandidateConstructors方法

  //第二次后置处理器
  Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

上面代码其实就是调用了AutowiredAnnotationBeanPostProcessor的determineCandidateConstructors
除去lookup处理,引起我注意的是
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
这行代码,这个candidateConstructorsCache是什么,他是一个Map<Class,Constructor[]>,可是这个缓存存在的意义是什么?原型bean根本走不到这里,在前面spring就对原型bean优化处理过了
单例bean第二次调用直接从单例池取出来,更加走不到这里了
那就是说常规手段根本不可能使用到此缓存,此缓存暂时不理解

					Constructor<?>[] rawCandidates;
					try {
						//拿到所有的构造器
						rawCandidates = beanClass.getDeclaredConstructors();
					}
					catch (Throwable ex) {
						throw new BeanCreationException(beanName,
								"Resolution of declared constructors on bean Class [" + beanClass.getName() +
								"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
					}
					//合格的构造器,我的理解是candidates.size要么是0要么是1(在没有autowired的情况)
					List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
					//@Autowired(true)的构造器
					Constructor<?> requiredConstructor = null;
					//默认无参构造器
					Constructor<?> defaultConstructor = null;
					//涉及kotlin知识,我们只需要明白常规java项目primaryConstructor一定是null
					Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
					//不是合成的构造器数量,不懂什么意思,但是常规构造器写法不管参数多少candidate.isSynthetic()都是false
					int nonSyntheticConstructors = 0;
					//遍历所有构造器
					for (Constructor<?> candidate : rawCandidates) {
						if (!candidate.isSynthetic()) {
							//每次都会加
							nonSyntheticConstructors++;
						}
						//这个非kotlin环境一定为null
						else if (primaryConstructor != null) {
							continue;
						}
						//找到该构造器Autowired注解属性
						AnnotationAttributes ann = findAutowiredAnnotation(candidate);
						//该构造器没有加Autowired
						if (ann == null) {
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							//这里什么情况会不等,一帮不会进if
							if (userClass != beanClass) {
								try {
									Constructor<?> superCtor =
											userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);
								}
								catch (NoSuchMethodException ex) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						//有Autowired注解
						if (ann != null) {
							//我们说requiredConstructor就是存储Autowired(true)的那个构造器
							//已经有requiredConstructor了,又来一个Autowired直接报错
							if (requiredConstructor != null) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}
							//取出Autowired的属性值required
							boolean required = determineRequiredStatus(ann);
							//如果是true
							if (required) {
								//合格的构造器集合已经有了,我们说这个构造器集合最多只能有一个,所以直接报错
								//为什么spring设计合格的构造器集合最多只能有一个,因为返回多个给调用方也没用啊,他还是不知道用哪个,
								// 所以决策构造器最好的方式就是要不返回一个,要不返回null(没有autowired的情况)
								if (!candidates.isEmpty()) {
									throw new BeanCreationException(beanName,
											"Invalid autowire-marked constructors: " + candidates +
											". Found constructor with 'required' Autowired annotation: " +
											candidate);
								}
								//给requiredConstructor赋值
								requiredConstructor = candidate;
							}
							//添加到合格构造器集合
							candidates.add(candidate);
						}
						//给默认构造器赋值
						else if (candidate.getParameterCount() == 0) {
							defaultConstructor = candidate;
						}
					}
					//合格构造器集合不空
					if (!candidates.isEmpty()) {
						//Autowried(false)会出现candidates不空,而requiredConstructor的现象
						if (requiredConstructor == null) {
							//添加默认的
							if (defaultConstructor != null) {
								candidates.add(defaultConstructor);
							}
							//candidates只有一个构造器(有参) 
							else if (candidates.size() == 1 && logger.isInfoEnabled()) {
								logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
										"': single autowire-marked constructor flagged as optional - " +
										"this constructor is effectively required since there is no " +
										"default constructor to fall back to: " + candidates.get(0));
							}
						}
						
						candidateConstructors = candidates.toArray(new Constructor<?>[0]);
					}
					//只有一个构造器(有参),直接返回这个就行了
					else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
						candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
					}
					//非kotlin不会进
					else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
							defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
					}
					//非kotlin不会进
					else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
						candidateConstructors = new Constructor<?>[] {primaryConstructor};
					}
					else {
						candidateConstructors = new Constructor<?>[0];
					}
					this.candidateConstructorsCache.put(beanClass, candidateConstructors);
				}
			}
		}
		//要不返回一个要不返回null(如果返回了null,那么调用方用无参实例化就好了)
		return (candidateConstructors.length > 0 ? candidateConstructors : null);

在没有autowried情况下,上面方法的返回只有两种情况
情况一:只有一个构造器(并且含有参数)返回该构造器,这种情况太确定了,只好返回这个,并且参数会给你装配,如果参数不在spring容器,会报错
情况二:除了情况一,都是返回null
spring之所以这么设计在上面代码的注释已经解释了一部分原因,还有一个原因是spring bean的装配模式默认是NO,也就是手动装配,你给了很多的构造器,那些构造器参数spring没办法帮你自动装配。(猜测原因,个人有个人见解)
在有autowried的情况下
情况一:autowried(true)且autowried只有一个,返回此构造器即可(参数不在spring容器会报错)
情况二:一个或多个autowried(false)有参构造+无参构造+其他任何不带autowried的构造,返回autowried(false)有参构造+无参构造
因为spring不知道你加了autowried这个构造器有没有用,只能返回这个加上无参
情况三:autowried(true)+ autowried(true)抛异常 ,不可以用两个构造器
情况四:autowried(true)+ autowried(false)抛异常,这种情况我目前不太能理解,按我的逻辑返回autowried(true)就好了

经过上面方法决策后spring返回的构造器可能是null,可能有一个,可能有多个,spring还要进行一些列复杂操作,才能决策出最合适的构造器

接下来就是自动装配的逻辑了,在说这个之前,先理一下什么情况会进入自动装配逻辑,如下

		//第二次后置处理器 决策构造器
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		//ctors可能为null,可能有一个,可能有多个(存在autowired(false)的情况)
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			//四个条件分别是ctors不空,装配模式是构造器装配,bd有构造器参数,构造器参数args不空
			//ctors有一个:即只有(Autoiwired(true)这个)或者只有一个构造器(有参),spring要走下面逻辑自动给构造器装配参数
			//ctors有多个:即存在多个Autoiwired(false)或 一个或多个Autoiwired(false)+无参
			//这种情况比较复杂:他在自动装配逻辑里面还是要选择出最合适的那个,
			// 原则是选择参数最多的那个(并且参数都在spring容器里),如果没有一个这样的构造器,则使用无参构造器
			
			//第二个条件装配模式是构造器装配,这个我们得实现spring扩展接口BeanFactoryPostProcessor手动改成构造器装配
			//这样不管上面的ctors是什么,他都会走一遍自动装配逻辑
			
			//第三个条件 也可以实现BeanFactoryPostProcessor手动添加构造器参数
			//第四个条件可忽略(getBean传过来的就是null)
			
			//可以理解为自动装配逻辑
			return autowireConstructor(beanName, mbd, ctors, args);
		}
		//...省略
		//ctors==null并且使用手动装配模式NO,默认走无参
		return instantiateBean(beanName, mbd);//使用无参

下面的重点就是autowireConstructor这个方法了

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
			@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {

		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);
		//最终使用的构造器
		Constructor<?> constructorToUse = null;
		//最终使用的构造器的参数封装的Holder对象
		ArgumentsHolder argsHolderToUse = null;
		//最终使用的构造器的参数
		Object[] argsToUse = null;
		//这个参数是从getBean传null过来的,大多数情况是null
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
			}
		}

		if (constructorToUse == null || argsToUse == null) {
			// Take specified constructors, if any.

			Constructor<?>[] candidates = chosenCtors;
			if (candidates == null) {
				Class<?> beanClass = mbd.getBeanClass();
				try {
					candidates = (mbd.isNonPublicAccessAllowed() ?
							beanClass.getDeclaredConstructors() : beanClass.getConstructors());
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Resolution of declared constructors on bean Class [" + beanClass.getName() +
							"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
				}
			}

			//只有一个默认构造器
			if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
				Constructor<?> uniqueCandidate = candidates[0];
				if (uniqueCandidate.getParameterCount() == 0) {
					synchronized (mbd.constructorArgumentLock) {
						//给创建原型bean提供快捷方式,相当于把构造器缓存下来,下次直接用
						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
						mbd.constructorArgumentsResolved = true;
						mbd.resolvedConstructorArguments = EMPTY_ARGS;
					}
					bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
					return bw;
				}
			}

			// Need to resolve the constructor.
			//是否需要自动装配,如果有构造器或者装配模式是构造器装配都要进行自动装配
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			int minNrOfArgs;//参数的最小个数,这个参数的作用是,当遍历构造器集合时发现某个构造器参数个数小于此值,直接continue
			if (explicitArgs != null) {
				//有构造器参数的话,参数最小个数赋值为这个长度,一般minNrOfArgs都是0
				minNrOfArgs = explicitArgs.length;
			}
			else {
				//我们很少给mbd设置ConstructorArgumentValues,故这里执行完minNrOfArgs还是0
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				resolvedValues = new ConstructorArgumentValues();
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}
			//给构造器排序,排序规则:public>protected>private,相同访问权限下参数个数越多越排前面
			AutowireUtils.sortConstructors(candidates);
			//最小类型差异权重,此值越大差异越大,初始化为最大差异
			int minTypeDiffWeight = Integer.MAX_VALUE;
			//模棱两可的构造器集合,用于存储spring都不确定的构造器集合
			Set<Constructor<?>> ambiguousConstructors = null;
			//异常集合,例如,某个构造器参数不在spring容器中
			LinkedList<UnsatisfiedDependencyException> causes = null;
			//遍历构造器
			for (Constructor<?> candidate : candidates) {
				//构造器参数类型数组
				Class<?>[] paramTypes = candidate.getParameterTypes();
				//已经有最终构造器&&已经有最终构造器参数&&最终构造器参数长度>当前构造器参数长度(直接跳出循环,使用constructorToUse)
				if (constructorToUse != null && argsToUse != null && argsToUse.length > paramTypes.length) {
					break;
				}
				//当前构造器参数长度<构造器参数的最小个数,这种情况当前构造器肯定不合格,直接抛弃当前构造器
				if (paramTypes.length < minNrOfArgs) {
					continue;
				}
				//参数Holder
				ArgumentsHolder argsHolder;
				//上面new过了,不为null
				if (resolvedValues != null) {
					try {
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
						if (paramNames == null) {
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								//到这里就找到了当前构造器的参数的名字数组paramNames
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						//这行代码极其复杂,我不打算往下深究了,但是我大概知道里面在做什么?
						//其实就是找出当前构造器的参数列表放到ArgumentsHolder对象中,但是这可能又会涉及到循环依赖的问题
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
						//到这里构造器参数就找到了
					}
					//如果构造器里面的参数不在spring容器,应该会进入catch
					catch (UnsatisfiedDependencyException ex) {
						if (logger.isTraceEnabled()) {
							logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
						}
						// Swallow and try next constructor.
						if (causes == null) {
							causes = new LinkedList<>();
						}
						//加入异常集合
						causes.add(ex);
						continue;
					}
				}
				else {
					//进了else 说明explicitArgs不为null
					// Explicit arguments given -> arguments length must match exactly.
					if (paramTypes.length != explicitArgs.length) {
						//如果当前构造器参数长度不等于我们传的构造器参数长度,那么肯定可以抛弃当前构造器
						continue;
					}
					//直接用我们给的参数new一个ArgumentsHolder
					argsHolder = new ArgumentsHolder(explicitArgs);
				}
				//这是计算差异权重的代码
				//它会根据lenientConstructorResolution的值去选取一种算法
				//为true时选 getTypeDifferenceWeight(默认为true)
				//false选 getAssignabilityWeight
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				//如果计算出来的权重<最小差异权重,那么说明我是更合适的,就要使用我这个构造器
				if (typeDiffWeight < minTypeDiffWeight) {
					//记录当前构造器及参数
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					//更新最小差异权重
					minTypeDiffWeight = typeDiffWeight;
					//重置ambiguousConstructors为null
					ambiguousConstructors = null;
				}
				//如果已经有了最终的构造器可供使用&&当前构造器计算出来的权重==最小差异权重
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					//这下spring就为难了,他把这两个构造器加到模糊集合了
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}

			if (constructorToUse == null) {
				if (causes != null) {
					UnsatisfiedDependencyException ex = causes.removeLast();
					for (Exception cause : causes) {
						this.beanFactory.onSuppressedException(cause);
					}
					throw ex;
				}
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Could not resolve matching constructor " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
			}
			//如果有模糊构造器&&lenientConstructorResolution=false 抛异常,但是lenientConstructorResolution默认true
			//即不会抛异常,spring会拿constructorToUse去实例化bean
			//可是试一下这种情况,有两个构造器都只有一个参数,并且这个参数都在都在spring容器中,那么spring就不知道到底用哪个
			//这种情况下lenientConstructorResolution=true的意思是用第一个发现合格的构造器,然后会把这两个构造器加入模糊集合,不抛异常
			//我们也可以实现spring扩展接口手动修改lenientConstructorResolution=false,那么就会抛异常
			//有点像找老婆,找到两个一样漂亮的,有两种策略,一种是随便选一个(这里是选第一个),还一种是一个都不选,可以两个都要吗(手动滑稽)
			else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Ambiguous constructor matches found in bean '" + beanName + "' " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
						ambiguousConstructors);
			}

			if (explicitArgs == null && argsHolderToUse != null) {
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		Assert.state(argsToUse != null, "Unresolved constructor arguments");
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
		return bw;
	}

决策构造器到这里就算告一段落了,上面很多地方提到了BeanFactoryPostProcessoer接口,下面给一个例子

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		GenericBeanDefinition bd = (GenericBeanDefinition) beanFactory.getBeanDefinition("userService");
		bd.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);//构造器自动装配(如果设置自动注入,那么程序员手动添加的constrctorArgumentValues就不会生效了
		)
		bd.setLenientConstructorResolution(false);//false代表 当遇到两个权重一样的构造器抛异常,严于律己,不随便选
	}
}

第三次执行后置处理-处理@autowired,@Value和@resource

在说第三次后置处理器之前,我们先想一想spring决策完构造器new了空对象之后会做什么,如果是我肯定会去查找属性和方法,其中构造方法不需要再次解析(构造器已经被选出来了),但是查找出的属性和方法要不要进行DI和执行,答案是不要的,如果我们此时对属性进行填充,那么属性之间循环引用的问题就解决不了了,因此我们只需要先把加了Autowired和Resource的属性和方法缓存起来,待到我们把空对象提前暴露到早期单例池之后,在进行DI操作,这是解决循环依赖的关键。
下面我们来看看他是如何缓存属性和方法的

//第三次执行后置处理的入口
AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
//遍历所有的bean后置处理器,把实现了MergedBeanDefinitionPostProcessor的拿出来执行postProcessMergedBeanDefinition方法
//这里我们只需要关注CommonAnnotationBeanPostProcessor(存储@Resource的属性和方法)和AutowiredAnnotationBeanPostProcessor(存储@Autowired和@Value的属性和方法)
//applyMergedBeanDefinitionPostProcessors:通过后置处理器应用合并bd(通过后置处理器从合并bd里面找出@Autowired和@Resource的属性和方法)
//合并bd 其实我之前一直不理解,还好有子路大神带着,感谢,抱拳!
//其实就是bd可能有父子关系,我们需要把子bd的属性覆盖掉父bd的属性,覆盖完之后的父bd就是RootBeanDefinition,这个就是一个MergedBeanDefinition(其实可以理解spring偷了懒,不过是很聪明的偷懒方式,她省了一个MergedBeanDefinition类的书写)
//这里我们直接从合并bd里面查找@Autowired,@Value和@Resource的属性和方法,那么什么时候做的合并bd,其实在refresh()里的invokeBeanFactoryProcessor里就已经合并了

下面我们只分析AutowiredAnnotationBeanPostProcessor,另一个几乎一样的

InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);//查找@Autowired的属性和方法
metadata.checkConfigMembers(beanDefinition);//意义不是很大
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
		//DI元数据缓存的key
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		//使用缓存提升效率
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		//上面没有
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				//双重检查
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					//现在用不到这个if,之后DI可能用到
					if (metadata != null) {
						metadata.clear(pvs);
					}
					//查找@Autowired的属性和方法
					metadata = buildAutowiringMetadata(clazz);
					//添加缓存
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		//为什么要定义两个list  elements  currElements ,定义一个直接add不行吗
		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
			//查找@Autowired属性
			//根绝targetClass查找出所有的field,遍历field数组,回调表达式
		ReflectionUtils.doWithLocalFields(targetClass, field -> {
				//判断属性是否有@Value或者@Autowired
				AnnotationAttributes ann = findAutowiredAnnotation(field);
				if (ann != null) {
					//static不可以加@Autowired,@Value
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					//@Autowired,@Value的Required值
					boolean required = determineRequiredStatus(ann);
					//添加进去  AutowiredFieldElement(field,boolean) extends 
					// InjectionMetadata.InjectedElement(Member member(member可以是方法,属性,构造器);boolean isField)
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});
			//省略方法查找
			elements.addAll(0, currElements);
			//找父类
			targetClass = targetClass.getSuperclass();
		}
		//直到Object
		while (targetClass != null && targetClass != Object.class);

		return new InjectionMetadata(clazz, elements);
	}

@Nullable
	private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
		if (ao.getAnnotations().length > 0) {  // autowiring annotations have to be local
			//this.autowiredAnnotationTypes是下面代码加进去的,是Autowired.class,Value.class
			for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
				AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
				if (attributes != null) {
					return attributes;
				}
			}
		}
		return null;
	}


public AutowiredAnnotationBeanPostProcessor() {
		this.autowiredAnnotationTypes.add(Autowired.class);
		this.autowiredAnnotationTypes.add(Value.class);
		try {
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

到此的第三次后置处理器就差不多执行完了,属性和方法都存储在injectionMetadataCache缓存中

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

目录 · · · · · · 第1章 面试的流程 1 1.1 面试官谈面试 1 1.2 面试的3种形式 2 1.2.1 电话面试 2 1.2.2 共享桌面远程面试 3 1.2.3 现场面试 4 1.3 面试的3个环节 5 1.3.1 行为面试环节 5 1.3.2 技术面试环节 10 1.3.3 应聘者提问环节 17 1.4 本章小结 18 第2章 面试需要的基础知识 20 2.1 面试官谈基础知识 20 2.2 编程语言 21 2.2.1 C++ 22 2.2.2 C# 27 2.3 数据结构 36 2.3.1 数组 36 2.3.2 字符串 47 2.3.3 链表 55 2.3.4 树 59 2.3.5 栈和队列 67 2.4 算法和数据操作 71 2.4.1 递归和循环 72 2.4.2 查找和排序 78 2.4.3 回溯法 87 2.4.4 动态规划与贪婪算法 93 2.4.5 位运算 98 2.5 本章小结 103 第3章 高质量的代码 104 3.1 面试官谈代码质量 104 3.2 代码的规范性 105 3.3 代码的完整性 106 3.4 代码的鲁棒性 132 3.5 本章小结 151 第4章 解决面试题的思路 153 4.1 面试官谈面试思路 153 4.2 画图让抽象问题形象化 154 4.3 举例让抽象问题具体化 163 4.4 分解让复杂问题简单化 184 4.5 本章小结 199 第5章 优化时间和空间效率 201 5.1 面试官谈效率 201 5.2 时间效率 202 5.3 时间效率与空间效率的平衡 237 5.4 本章小结 254 第6章 面试中的各项能力 256 6.1 面试官谈能力 256 6.2 沟通能力和学习能力 257 6.3 知识迁移能力 260 6.4 抽象建模能力 293 6.5 发散思维能力 305 6.6 本章小结 313 第7章 两个面试案例 315 7.1 案例一:(面试题67)把字符串转换成整数 316 7.2 案例二:(面试题68)树中两个节点的最低公共祖先 324
©️2021 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值