2024年Java最全Spring IoC源码学习:createBean 详解(上)(1),腾讯T3亲自讲解

最后

笔者已经把面试题和答案整理成了面试专题文档

image

image

image

image

image

image

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

// 6.应用后置处理器MergedBeanDefinitionPostProcessor,允许修改MergedBeanDefinition,

// Autowired注解正是通过此方法实现注入类型的预解析

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

} catch (Throwable ex) {

throw new BeanCreationException(mbd.getResourceDescription(), beanName,

“Post-processing of merged bean definition failed”, ex);

}

mbd.postProcessed = true;

}

}

// Eagerly cache singletons to be able to resolve circular references

// even when triggered by lifecycle interfaces like BeanFactoryAware.

// 7.判断是否需要提早曝光实例:单例 && 允许循环依赖 && 当前bean正在创建中

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&

isSingletonCurrentlyInCreation(beanName));

if (earlySingletonExposure) {

if (logger.isDebugEnabled()) {

logger.debug(“Eagerly caching bean '” + beanName +

“’ to allow for resolving potential circular references”);

}

// 8.提前曝光beanName的ObjectFactory,用于解决循环引用

addSingletonFactory(beanName, new ObjectFactory() {

@Override

public Object getObject() throws BeansException {

// 8.1 应用后置处理器SmartInstantiationAwareBeanPostProcessor,允许返回指定bean的早期引用,若没有则直接返回bean

return getEarlyBeanReference(beanName, mbd, bean);

}

});

}

// Initialize the bean instance. 初始化bean实例。

Object exposedObject = bean;

try {

// 9.对bean进行属性填充;其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean实例

populateBean(beanName, mbd, instanceWrapper);

if (exposedObject != null) {

// 10.对bean进行初始化

exposedObject = initializeBean(beanName, exposedObject, mbd);

}

} catch (Throwable ex) {

if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {

throw (BeanCreationException) ex;

} else {

throw new BeanCreationException(

mbd.getResourceDescription(), beanName, “Initialization of bean failed”, ex);

}

}

if (earlySingletonExposure) {

// 11.如果允许提前曝光实例,则进行循环依赖检查

Object earlySingletonReference = getSingleton(beanName, false);

// 11.1 earlySingletonReference只有在当前解析的bean存在循环依赖的情况下才会不为空

if (earlySingletonReference != null) {

if (exposedObject == bean) {

// 11.2 如果exposedObject没有在initializeBean方法中被增强,则不影响之前的循环引用

exposedObject = earlySingletonReference;

} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {

// 11.3 如果exposedObject在initializeBean方法中被增强 && 不允许在循环引用的情况下使用注入原始bean实例

// && 当前bean有被其他bean依赖

// 11.4 拿到依赖当前bean的所有bean的beanName数组

String[] dependentBeans = getDependentBeans(beanName);

Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);

for (String dependentBean : dependentBeans) {

// 11.5 尝试移除这些bean的实例,因为这些bean依赖的bean已经被增强了,他们依赖的bean相当于脏数据

if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {

// 11.6 移除失败的添加到 actualDependentBeans

actualDependentBeans.add(dependentBean);

}

}

if (!actualDependentBeans.isEmpty()) {

// 11.7 如果存在移除失败的,则抛出异常,因为存在bean依赖了“脏数据”

throw new BeanCurrentlyInCreationException(beanName,

“Bean with name '” + beanName + “’ has been injected into other beans [” +

StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +

"] in its raw version as part of a circular reference, but has eventually been " +

"wrapped. This means that said other beans do not use the final version of the " +

"bean. This is often the result of over-eager type matching - consider using " +

“‘getBeanNamesOfType’ with the ‘allowEagerInit’ flag turned off, for example.”);

}

}

}

}

// Register bean as disposable.

try {

// 12.注册用于销毁的bean,执行销毁操作的有三种:自定义destroy方法、DisposableBean接口、DestructionAwareBeanPostProcessor

registerDisposableBeanIfNecessary(beanName, bean, mbd);

} catch (BeanDefinitionValidationException ex) {

throw new BeanCreationException(

mbd.getResourceDescription(), beanName, “Invalid destruction signature”, ex);

}

// 13.完成创建并返回

return exposedObject;

}

真正创建 bean 实例的方法,整个系列文章中的核心中的核心,很多代码是前后相关联的,需要反复阅读才能很好的理解。

3.根据 beanName、mbd、args,使用对应的策略创建 bean 实例,并返回包装类 BeanWrapper,见代码块4详解

由于创建 bean 实例的过程过长,限于篇幅关系,本文只介绍第 3 点的 createBeanInstance 方法,剩余的内容将在下一篇文章介绍

代码块4:createBeanInstance


protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {

// Make sure bean class is actually resolved at this point.

// 解析bean的类型信息

Class<?> beanClass = resolveBeanClass(mbd, beanName);

if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {

// beanClass不为空 && beanClass不是公开类(不是public修饰) && 该bean不允许访问非公共构造函数和方法,则抛异常

throw new BeanCreationException(mbd.getResourceDescription(), beanName,

"Bean class isn’t public, and non-public access not allowed: " + beanClass.getName());

}

// 1.如果存在工厂方法则使用工厂方法实例化bean对象

if (mbd.getFactoryMethodName() != null) {

return instantiateUsingFactoryMethod(beanName, mbd, args);

}

// Shortcut when re-creating the same bean…

// resolved: 构造函数或工厂方法是否已经解析过

boolean resolved = false;

// autowireNecessary: 是否需要自动注入(即是否需要解析构造函数参数)

boolean autowireNecessary = false;

if (args == null) {

// 2.加锁

synchronized (mbd.constructorArgumentLock) {

if (mbd.resolvedConstructorOrFactoryMethod != null) {

// 2.1 如果resolvedConstructorOrFactoryMethod缓存不为空,则将resolved标记为已解析

resolved = true;

// 2.2 根据constructorArgumentsResolved判断是否需要自动注入

autowireNecessary = mbd.constructorArgumentsResolved;

}

}

}

if (resolved) {

// 3.如果已经解析过,则使用resolvedConstructorOrFactoryMethod缓存里解析好的构造函数方法

if (autowireNecessary) {

// 3.1 需要自动注入,则执行构造函数自动注入

return autowireConstructor(beanName, mbd, null, null);

} else {

// 3.2 否则使用默认的构造函数进行bean的实例化

return instantiateBean(beanName, mbd);

}

}

// Need to determine the constructor…

// 4.应用后置处理器SmartInstantiationAwareBeanPostProcessor,拿到bean的候选构造函数

Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

if (ctors != null ||

mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||

mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {

// 5.如果ctors不为空 || mbd的注入方式为AUTOWIRE_CONSTRUCTOR || mdb定义了构造函数的参数值 || args不为空,则执行构造函数自动注入

return autowireConstructor(beanName, mbd, ctors, args);

}

// No special handling: simply use no-arg constructor.

// 6.没有特殊处理,则使用默认的构造函数进行bean的实例化

return instantiateBean(beanName, mbd);

}

创建实例的方法通常有以下几种:工厂方法、构造函数自动装配(通常指带有参数的构造函数)、简单实例化(默认的构造函数)。其中工厂方法现在基本不使用了,不再解析;简单实例化过程比较简单,也不解析;本文只对构造函数自动装配进行解析,该方法对应代码中的:3.1 和 5。

4.应用后置处理器 SmartInstantiationAwareBeanPostProcessor,拿到给定 bean 的候选构造函数,见代码块4.5详解

5.执行构造函数自动注入,见代码块5详解

代码块4.5:determineConstructorsFromBeanPostProcessors


protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName)

throws BeansException {

if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {

// 1.遍历所有的BeanPostProcessor

for (BeanPostProcessor bp : getBeanPostProcessors()) {

if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {

SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;

// 2.调用SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法,

// 该方法可以返回要用于beanClass的候选构造函数

// 例如:使用@Autowire注解修饰构造函数,则该构造函数在这边会被AutowiredAnnotationBeanPostProcessor找到

Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);

if (ctors != null) {

// 3.如果ctors不为空,则不再继续执行其他的SmartInstantiationAwareBeanPostProcessor

return ctors;

}

}

}

}

return null;

}

2.调用 SmartInstantiationAwareBeanPostProcessor 的 determineCandidateConstructors 方法,该方法可以返回要用于 beanClass 的候选构造函数。使用 @Autowire 注解修饰构造函数,则该构造函数在这边会被 AutowiredAnnotationBeanPostProcessor 找到,该内容会在之后介绍 @Autowire 的文章中单独介绍。

代码块5:autowireConstructor


protected BeanWrapper autowireConstructor(

String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {

return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);

}

public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,

Constructor<?>[] chosenCtors, final Object[] explicitArgs) {

// 定义bean包装类

BeanWrapperImpl bw = new BeanWrapperImpl();

this.beanFactory.initBeanWrapper(bw);

// 最终用于实例化的构造函数

Constructor<?> constructorToUse = null;

// 最终用于实例化的参数Holder

ArgumentsHolder argsHolderToUse = null;

// 最终用于实例化的构造函数参数

Object[] argsToUse = null;

// 1.解析出要用于实例化的构造函数参数

if (explicitArgs != null) {

// 1.1 如果explicitArgs不为空,则构造函数的参数直接使用explicitArgs

// 通过getBean方法调用时,显示指定了参数,则explicitArgs就不为null

argsToUse = explicitArgs;

}

else {

// 1.2 尝试从缓存中获取已经解析过的构造函数参数

Object[] argsToResolve = null;

synchronized (mbd.constructorArgumentLock) {

// 1.2.1 拿到缓存中已解析的构造函数或工厂方法

constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;

// 1.2.2 如果constructorToUse不为空 && mbd标记了构造函数参数已解析

if (constructorToUse != null && mbd.constructorArgumentsResolved) {

// Found a cached constructor…

// 1.2.3 从缓存中获取已解析的构造函数参数

argsToUse = mbd.resolvedConstructorArguments;

if (argsToUse == null) {

// 1.2.4 如果resolvedConstructorArguments为空,则从缓存中获取准备用于解析的构造函数参数,

// constructorArgumentsResolved为true时,resolvedConstructorArguments和

// preparedConstructorArguments必然有一个缓存了构造函数的参数

argsToResolve = mbd.preparedConstructorArguments;

}

}

}

if (argsToResolve != null) {

// 1.2.5 如果argsToResolve不为空,则对构造函数参数进行解析,

// 如给定方法的构造函数 A(int,int)则通过此方法后就会把配置中的(“1”,“1”)转换为(1,1)

argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);

}

}

// 2.如果构造函数没有被缓存,则通过配置文件获取

if (constructorToUse == null) {

// Need to resolve the constructor.

// 2.1 检查是否需要自动装配:chosenCtors不为空 || autowireMode为AUTOWIRE_CONSTRUCTOR

// 例子:当chosenCtors不为空时,代表有构造函数通过@Autowire修饰,因此需要自动装配

boolean autowiring = (chosenCtors != null ||

mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);

ConstructorArgumentValues resolvedValues = null;

// 构造函数参数个数

int minNrOfArgs;

if (explicitArgs != null) {

// 2.2 explicitArgs不为空,则使用explicitArgs的length作为minNrOfArgs的值

minNrOfArgs = explicitArgs.length;

}

else {

// 2.3 获得mbd的构造函数的参数值(indexedArgumentValues:带index的参数值;genericArgumentValues:通用的参数值)

ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();

// 2.4 创建ConstructorArgumentValues对象resolvedValues,用于承载解析后的构造函数参数的值

resolvedValues = new ConstructorArgumentValues();

// 2.5 解析mbd的构造函数的参数,并返回参数个数

minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);

// 注:这边解析mbd中的构造函数参数值,主要是处理我们通过xml方式定义的构造函数注入的参数,

// 但是如果我们是通过@Autowire注解直接修饰构造函数,则mbd是没有这些参数值的

}

// 3.确认构造函数的候选者

// Take specified constructors, if any.

// 3.1 如果入参chosenCtors不为空,则将chosenCtors的构造函数作为候选者

Constructor<?>[] candidates = chosenCtors;

if (candidates == null) {

Class<?> beanClass = mbd.getBeanClass();

try {

// 3.2 如果入参chosenCtors为空,则获取beanClass的构造函数

// (mbd是否允许访问非公共构造函数和方法 ? 所有声明的构造函数:公共构造函数)

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

}

}

// 3.3 对给定的构造函数排序:先按方法修饰符排序:public排非public前面,再按构造函数参数个数排序:参数多的排前面

AutowireUtils.sortConstructors(candidates);

// 最小匹配权重,权重越小,越接近我们要找的目标构造函数

int minTypeDiffWeight = Integer.MAX_VALUE;

Set<Constructor<?>> ambiguousConstructors = null;

LinkedList causes = null;

// 4.遍历所有构造函数候选者,找出符合条件的构造函数

for (Constructor<?> candidate : candidates) {

// 4.1 拿到当前遍历的构造函数的参数类型数组

Class<?>[] paramTypes = candidate.getParameterTypes();

if (constructorToUse != null && argsToUse.length > paramTypes.length) {

// Already found greedy constructor that can be satisfied ->

// do not look any further, there are only less greedy constructors left.

// 4.2 如果已经找到满足的构造函数 && 目标构造函数需要的参数个数大于当前遍历的构造函数的参数个数则终止,

// 因为遍历的构造函数已经排过序,后面不会有更合适的候选者了

break;

}

if (paramTypes.length < minNrOfArgs) {

// 4.3 如果当前遍历到的构造函数的参数个数小于我们所需的参数个数,则直接跳过该构造函数

continue;

}

ArgumentsHolder argsHolder;

if (resolvedValues != null) {

// 存在参数则根据参数值来匹配参数类型

try {

// 4.4 resolvedValues不为空,

// 4.4.1 获取当前遍历的构造函数的参数名称

// 4.4.1.1 解析使用ConstructorProperties注解的构造函数参数

String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);

if (paramNames == null) {

// 4.4.1.2 获取参数名称解析器

ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();

if (pnd != null) {

// 4.4.1.3 使用参数名称解析器获取当前遍历的构造函数的参数名称

paramNames = pnd.getParameterNames(candidate);

}

}

// 4.4.2 创建一个参数数组以调用构造函数或工厂方法,

// 主要是通过参数类型和参数名解析构造函数或工厂方法所需的参数(如果参数是其他bean,则会解析依赖的bean)

argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,

getUserDeclaredConstructor(candidate), autowiring);

}

catch (UnsatisfiedDependencyException ex) {

// 4.4.3 参数匹配失败,则抛出异常

if (this.beanFactory.logger.isTraceEnabled()) {

this.beanFactory.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 {

// 4.5 resolvedValues为空,则explicitArgs不为空,即给出了显式参数

// Explicit arguments given -> arguments length must match exactly.

// 4.5.1 如果当前遍历的构造函数参数个数与explicitArgs长度不相同,则跳过该构造函数

if (paramTypes.length != explicitArgs.length) {

continue;

}

// 4.5.2 使用显式给出的参数构造ArgumentsHolder

argsHolder = new ArgumentsHolder(explicitArgs);

}

// 4.6 根据mbd的解析构造函数模式(true: 宽松模式(默认),false:严格模式),

// 将argsHolder的参数和paramTypes进行比较,计算paramTypes的类型差异权重值

int typeDiffWeight = (mbd.isLenientConstructorResolution() ?

argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));

// Choose this constructor if it represents the closest match.

// 4.7 类型差异权重值越小,则说明构造函数越匹配,则选择此构造函数

if (typeDiffWeight < minTypeDiffWeight) {

// 将要使用的参数都替换成差异权重值更小的

constructorToUse = candidate;

argsHolderToUse = argsHolder;

argsToUse = argsHolder.arguments;

minTypeDiffWeight = typeDiffWeight;

// 如果出现权重值更小的候选者,则将ambiguousConstructors清空,允许之前存在权重值相同的候选者

ambiguousConstructors = null;

}

// 4.8 如果存在两个候选者的权重值相同,并且是当前遍历过权重值最小的

else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {

// 将这两个候选者都添加到ambiguousConstructors

if (ambiguousConstructors == null) {

ambiguousConstructors = new LinkedHashSet<Constructor<?>>();

ambiguousConstructors.add(constructorToUse);

}

ambiguousConstructors.add(candidate);

}

}

if (constructorToUse == null) {

// 5.如果最终没有找到匹配的构造函数,则进行异常处理

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

}

else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {

// 6.如果找到了匹配的构造函数,但是存在多个(ambiguousConstructors不为空) && 解析构造函数的模式为严格模式,则抛出异常

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) {

// 7.将解析的构造函数和参数放到缓存

argsHolderToUse.storeCache(mbd, constructorToUse);

}

}

try {

Object beanInstance;

// 8.根据实例化策略以及得到的构造函数及构造函数参数实例化bean

if (System.getSecurityManager() != null) {

final Constructor<?> ctorToUse = constructorToUse;

final Object[] argumentsToUse = argsToUse;

beanInstance = AccessController.doPrivileged(new PrivilegedAction() {

@Override

public Object run() {

return beanFactory.getInstantiationStrategy().instantiate(

mbd, beanName, beanFactory, ctorToUse, argumentsToUse);

}

}, beanFactory.getAccessControlContext());

}

else {

beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(

mbd, beanName, this.beanFactory, constructorToUse, argsToUse);

}

// 9.将构造的实例加入BeanWrapper中,并返回

bw.setBeanInstance(beanInstance);

return bw;

}

catch (Throwable ex) {

throw new BeanCreationException(mbd.getResourceDescription(), beanName,

“Bean instantiation via constructor failed”, ex);

}

}

例子:

这边 2.3 - 2.5 解析的 mbd 的构造函数参数值主要是针对通过 XML 注入的方式,例如以下例子:

sping 配置文件:

sing

basketball

构造函数参数中带 index 的会被解析到 ConstructorArgumentValues.indexedArgumentValues,不带的会被解析到 ConstructorArgumentValues.genericArgumentValues。

DemoServiceImpl.java

@Service

public class DemoServiceImpl implements DemoService {

private Integer id;

private Integer age;

private String name;

private List skillList;

private UserService userService;

public DemoServiceImpl(Integer id, Integer age, String name, List skillList, UserService userService) {

this.id = id;

this.age = age;

this.name = name;

this.skillList = skillList;

this.userService = userService;

}

@Override

public void sayHello() {

}

}

2.5 解析 mbd 的构造函数的参数,并返回参数个数,见代码块6详解

4.4.2 创建一个参数数组以调用构造函数或工厂方法,主要是通过参数类型和参数名解析构造函数或工厂方法所需的参数(如果参数是其他 bean,则会解析依赖的 bean),见代码块7详解

7.将解析的构造函数和参数放到缓存,见代码块19详解

代码块6:resolveConstructorArguments


private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,

ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {

// 1.构建bean定义值解析器

TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();

TypeConverter converter = (customConverter != null ? customConverter : bw);

BeanDefinitionValueResolver valueResolver =

new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);

// 2.minNrOfArgs初始化为indexedArgumentValues和genericArgumentValues的的参数个数总和

int minNrOfArgs = cargs.getArgumentCount();

// 3.遍历解析带index的参数值

for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {

int index = entry.getKey();

if (index < 0) {

// index从0开始,不允许小于0

throw new BeanCreationException(mbd.getResourceDescription(), beanName,

"Invalid constructor argument index: " + index);

}

// 3.1 如果index大于minNrOfArgs,则修改minNrOfArgs

if (index > minNrOfArgs) {

// index是从0开始,并且是有序递增的,所以当有参数的index=5时,代表该方法至少有6个参数

minNrOfArgs = index + 1;

}

ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();

// 3.2 解析参数值

if (valueHolder.isConverted()) {

// 3.2.1 如果参数值已经转换过,则直接将index和valueHolder添加到resolvedValues的indexedArgumentValues属性

resolvedValues.addIndexedArgumentValue(index, valueHolder);

} else {

// 3.2.2 如果值还未转换过,则先进行转换

Object resolvedValue =

valueResolver.resolveValueIfNecessary(“constructor argument”, valueHolder.getValue());

// 3.2.3 使用转换后的resolvedValue构建新的ValueHolder

ConstructorArgumentValues.ValueHolder resolvedValueHolder =

new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());

// 3.2.4 将转换前的valueHolder保存到新的ValueHolder的source属性

resolvedValueHolder.setSource(valueHolder);

// 3.2.5 将index和新的ValueHolder添加到resolvedValues的indexedArgumentValues属性

resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);

}

}

// 4.遍历解析通用参数值(不带index)

for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {

if (valueHolder.isConverted()) {

// 4.1 如果参数值已经转换过,则直接将valueHolder添加到resolvedValues的genericArgumentValues属性

resolvedValues.addGenericArgumentValue(valueHolder);

} else {

// 4.2 如果值还未转换过,则先进行转换

Object resolvedValue =

valueResolver.resolveValueIfNecessary(“constructor argument”, valueHolder.getValue());

// 4.3 使用转换后的resolvedValue构建新的ValueHolder

ConstructorArgumentValues.ValueHolder resolvedValueHolder =

new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());

// 4.4 将转换前的valueHolder保存到新的ValueHolder的source属性

resolvedValueHolder.setSource(valueHolder);

// 4.5 将新的ValueHolder添加到resolvedValues的genericArgumentValues属性

resolvedValues.addGenericArgumentValue(resolvedValueHolder);

}

}

// 5.返回构造函数参数的个数

return minNrOfArgs;

}

代码块7:createArgumentArray


private ArgumentsHolder createArgumentArray(

String beanName, RootBeanDefinition mbd, ConstructorArgumentValues resolvedValues,

BeanWrapper bw, Class<?>[] paramTypes, String[] paramNames, Object methodOrCtor,

boolean autowiring) throws UnsatisfiedDependencyException {

TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();

// 获取类型转换器

TypeConverter converter = (customConverter != null ? customConverter : bw);

// 新建一个ArgumentsHolder来存放匹配到的参数

ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);

Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =

new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length);

Set autowiredBeanNames = new LinkedHashSet(4);

// 1.遍历参数类型数组

for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {

// 拿到当前遍历的参数类型

Class<?> paramType = paramTypes[paramIndex];

// 拿到当前遍历的参数名

String paramName = (paramNames != null ? paramNames[paramIndex] : “”);

// Try to find matching constructor argument value, either indexed or generic.

// 2.查找当前遍历的参数,是否在mdb对应的bean的构造函数参数中存在index、类型和名称匹配的

ConstructorArgumentValues.ValueHolder valueHolder =

resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);

// If we couldn’t find a direct match and are not supposed to autowire,

// let’s try the next generic, untyped argument value as fallback:

// it could match after type conversion (for example, String -> int).

// 3.如果我们找不到直接匹配并且不应该自动装配,那么让我们尝试下一个通用的无类型参数值作为降级方法:它可以在类型转换后匹配(例如,String - > int)。

if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {

valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);

}

if (valueHolder != null) {

// 4.valueHolder不为空,存在匹配的参数

// We found a potential match - let’s give it a try.

// Do not consider the same value definition multiple times!

// 将valueHolder添加到usedValueHolders

usedValueHolders.add(valueHolder);

// 原始属性值

Object originalValue = valueHolder.getValue();

// 转换后的属性值

Object convertedValue;

if (valueHolder.isConverted()) {

// 4.1 如果valueHolder已经转换过

// 4.1.1 则直接获取转换后的值

convertedValue = valueHolder.getConvertedValue();

// 4.1.2 将convertedValue作为args在paramIndex位置的预备参数

args.preparedArguments[paramIndex] = convertedValue;

} else {

// 4.2 如果valueHolder还未转换过

// 4.2.1 拿到原始的ValueHolder

ConstructorArgumentValues.ValueHolder sourceHolder =

(ConstructorArgumentValues.ValueHolder) valueHolder.getSource();

// 4.2.2 拿到原始参数值

Object sourceValue = sourceHolder.getValue();

// 4.2.3 将方法(此处为构造函数)和参数索引封装成MethodParameter(MethodParameter是封装方法和参数索引的工具类)

MethodParameter methodParam = MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex);

try {

// 4.2.4 将原始值转换为paramType类型的值(如果类型无法转,抛出TypeMismatchException)

convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);

// TODO re-enable once race condition has been found (SPR-7423)

/*

if (originalValue == sourceValue || sourceValue instanceof TypedStringValue) {

// Either a converted value or still the original one: store converted value.

sourceHolder.setConvertedValue(convertedValue);

args.preparedArguments[paramIndex] = convertedValue;

}

else {

*/

// 4.2.5 args标记为需要解析

args.resolveNecessary = true;

// 4.2.6 将convertedValue作为args在paramIndex位置的预备参数

args.preparedArguments[paramIndex] = sourceValue;

// }

} catch (TypeMismatchException ex) {

// 4.2.7 如果类型转换失败,则抛出异常

throw new UnsatisfiedDependencyException(

mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),

“Could not convert argument value of type [” +

ObjectUtils.nullSafeClassName(valueHolder.getValue()) +

“] to required type [” + paramType.getName() + "]: " + ex.getMessage());

}

}

// 4.3 将convertedValue作为args在paramIndex位置的参数

args.arguments[paramIndex] = convertedValue;

// 4.4 将originalValue作为args在paramIndex位置的原始参数

args.rawArguments[paramIndex] = originalValue;

} else {

// 5.valueHolder为空,不存在匹配的参数

// 5.1 将方法(此处为构造函数)和参数索引封装成MethodParameter

MethodParameter methodParam = MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex);

// No explicit match found: we’re either supposed to autowire or

// have to fail creating an argument array for the given constructor.

// 5.2 找不到明确的匹配,并且不是自动装配,则抛出异常

if (!autowiring) {

throw new UnsatisfiedDependencyException(

mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),

“Ambiguous argument values for parameter of type [” + paramType.getName() +

“] - did you specify the correct bean references as arguments?”);

}

try {

// 5.3 如果是自动装配,则调用用于解析自动装配参数的方法,返回的结果为依赖的bean实例对象

// 例如:@Autowire修饰构造函数,自动注入构造函数中的参数bean就是在这边处理

Object autowiredArgument =

resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter);

// 5.4 将通过自动装配解析出来的参数赋值给args

args.rawArguments[paramIndex] = autowiredArgument;

args.arguments[paramIndex] = autowiredArgument;

args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();

args.resolveNecessary = true;

} catch (BeansException ex) {

// 5.5 如果自动装配解析失败,则会抛出异常

throw new UnsatisfiedDependencyException(

mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);

}

}

}

// 6.如果依赖了其他的bean,则注册依赖关系

for (String autowiredBeanName : autowiredBeanNames) {

this.beanFactory.registerDependentBean(autowiredBeanName, beanName);

if (this.beanFactory.logger.isDebugEnabled()) {

this.beanFactory.logger.debug(“Autowiring by type from bean name '” + beanName +

"’ via " + (methodOrCtor instanceof Constructor ? “constructor” : “factory method”) +

" to bean named ‘" + autowiredBeanName + "’");

}

}

return args;

}

5.3 如果是自动装配,则调用用于解析自动装配参数的方法,返回的结果为依赖的 bean 实例对象,见代码块8详解

代码块8:resolveAutowiredArgument


protected Object resolveAutowiredArgument(

MethodParameter param, String beanName, Set autowiredBeanNames, TypeConverter typeConverter) {

// 1.如果参数类型为InjectionPoint

if (InjectionPoint.class.isAssignableFrom(param.getParameterType())) {

// 1.1 拿到当前的InjectionPoint(存储了当前正在解析依赖的方法参数信息,DependencyDescriptor)

InjectionPoint injectionPoint = currentInjectionPoint.get();

if (injectionPoint == null) {

// 1.2 当前injectionPoint为空,则抛出异常:目前没有可用的InjectionPoint

throw new IllegalStateException("No current InjectionPoint available for " + param);

}

// 1.3 返回当前的InjectionPoint

return injectionPoint;

}

// 2.解析指定依赖,DependencyDescriptor:将MethodParameter的方法参数索引信息封装成DependencyDescriptor

return this.beanFactory.resolveDependency(

new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);

}

2.解析指定依赖,这边的 DependencyDescriptor 主要是封装了依赖的方法和参数的信息,见代码块9详解

代码块9:resolveDependency


@Override

public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,

Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());

if (javaUtilOptionalClass == descriptor.getDependencyType()) {

// 1.javaUtilOptionalClass类注入的特殊处理

return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);

} else if (ObjectFactory.class == descriptor.getDependencyType() ||

// 2.ObjectFactory类注入的特殊处理

ObjectProvider.class == descriptor.getDependencyType()) {

return new DependencyObjectProvider(descriptor, requestingBeanName);

} else if (javaxInjectProviderClass == descriptor.getDependencyType()) {

// 3.javaxInjectProviderClass类注入的特殊处理

return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);

} else {

// 4.通用类注入的处理

// 4.1 如有必要,请获取延迟解析代理

Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(

descriptor, requestingBeanName);

if (result == null) {

// 4.2 解析依赖关系,返回的result为创建好的依赖对象的bean实例

result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);

}

return result;

}

}

4.2 解析依赖关系,返回的 result 为创建好的依赖对象的 bean 实例,见代码块10详解

代码块10:doResolveDependency


public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,

Set autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

// 1.设置当前的descriptor(存储了方法参数等信息)为当前注入点

InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);

try {

// 2.如果是ShortcutDependencyDescriptor,则直接通过getBean方法获取Bean实例,并返回;否则返回null

Object shortcut = descriptor.resolveShortcut(this);

if (shortcut != null) {

return shortcut;

}

// 3.拿到descriptor包装的方法的参数类型(通过参数索引定位到具体的参数)

Class<?> type = descriptor.getDependencyType();

// 4.用于支持spring中新增的注解@Value(确定给定的依赖项是否声明Value注解,如果有则拿到值)

Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);

if (value != null) {

if (value instanceof String) {

String strVal = resolveEmbeddedValue((String) value);

BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);

value = evaluateBeanDefinitionString(strVal, bd);

}

TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());

// 4.1 如果使用了@Value注解,则将解析到的值转换成所需的类型并返回

return (descriptor.getField() != null ?

converter.convertIfNecessary(value, type, descriptor.getField()) :

converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));

}

// 5.解析MultipleBean(下文的MultipleBean都是指类型为:Array、Collection、Map)

Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);

if (multipleBeans != null) {

// 5.1 如果确实是容器类型的属性,则直接返回解析结果

return multipleBeans;

}

// 6.查找与所需类型匹配的Bean实例(matchingBeans,key:beanName;value:匹配的bean实例,或者匹配的bean实例的类型)

Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

if (matchingBeans.isEmpty()) {

// 6.1 如果require属性为true,而找到的匹配Bean却为空则抛出异常

if (isRequired(descriptor)) {

raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);

}

// 6.2 如果require属性为false,而找到的匹配Bean却为空,则返回nul

return null;

}

String autowiredBeanName;

Object instanceCandidate;

if (matchingBeans.size() > 1) {

// 7.非MultipleBean,但是有多个候选者

// 7.1 从多个候选者中选出最优的那个

autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);

if (autowiredBeanName == null) {

if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {

return descriptor.resolveNotUnique(type, matchingBeans);

} else {

// In case of an optional Collection/Map, silently ignore a non-unique case:

// possibly it was meant to be an empty collection of multiple regular beans

// (before 4.3 in particular when we didn’t even look for collection beans).

return null;

}

}

// 7.2.拿到autowiredBeanName对应的value(bean实例或bean实例类型)

instanceCandidate = matchingBeans.get(autowiredBeanName);

} else {

// 8.只找到了一个候选者,则直接使用该候选者

Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();

autowiredBeanName = entry.getKey();

instanceCandidate = entry.getValue();

}

if (autowiredBeanNames != null) {

// 9.将依赖的beanName加到autowiredBeanNames中

autowiredBeanNames.add(autowiredBeanName);

}

// 10.如果instanceCandidate为Class,则instanceCandidate为bean实例的类型,执行descriptor.resolveCandidate方法,

// 通过getBean方法获取bean实例并返回;如果instanceCandidate不是Class,则instanceCandidate为bean实例,直接返回该实例

return (instanceCandidate instanceof Class ?

descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);

} finally {

// 11.执行结束,将注入点修改成原来的注入点

ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);

}

}

2.如果是 ShortcutDependencyDescriptor,则直接通过 getBean 方法获取 bean 实例,并返回;否则返回 null。

通过构造函数注入依赖的 bean 实例的整个过程是不会出现涉及到 ShortcutDependencyDescriptor 的。ShortcutDependencyDescriptor 主要用于 @Autowire 注解,在解析 @Autowire 注解的时候,当第一次注入依赖的 bean 实例后,会将该依赖的 bean 的信息封装成 ShortcutDependencyDescriptor ,放到缓存中去,下一次需要依赖注入该 bean 时,可以直接快速的拿到该 bean 实例。

6.查找与所需类型匹配的 bean 实例,这边的返回结果 matchingBeans 的 key 是 beanName,而 value 有两种情况:一种是匹配的 bean 实例,另一种是匹配的 bean 实例的类型,见代码块11详解

7.1 从多个候选者中选出最优的那个,见代码块16详解

代码块11:findAutowireCandidates


protected Map<String, Object> findAutowireCandidates(

String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {

那么如何才能正确的掌握Redis呢?

为了让大家能够在Redis上能够加深,所以这次给大家准备了一些Redis的学习资料,还有一些大厂的面试题,包括以下这些面试题

  • 并发编程面试题汇总

  • JVM面试题汇总

  • Netty常被问到的那些面试题汇总

  • Tomcat面试题整理汇总

  • Mysql面试题汇总

  • Spring源码深度解析

  • Mybatis常见面试题汇总

  • Nginx那些面试题汇总

  • Zookeeper面试题汇总

  • RabbitMQ常见面试题汇总

JVM常频面试:

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

Mysql面试题汇总(一)

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

Mysql面试题汇总(二)

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

Redis常见面试题汇总(300+题)

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

则instanceCandidate为bean实例的类型,执行descriptor.resolveCandidate方法,

// 通过getBean方法获取bean实例并返回;如果instanceCandidate不是Class,则instanceCandidate为bean实例,直接返回该实例

return (instanceCandidate instanceof Class ?

descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);

} finally {

// 11.执行结束,将注入点修改成原来的注入点

ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);

}

}

2.如果是 ShortcutDependencyDescriptor,则直接通过 getBean 方法获取 bean 实例,并返回;否则返回 null。

通过构造函数注入依赖的 bean 实例的整个过程是不会出现涉及到 ShortcutDependencyDescriptor 的。ShortcutDependencyDescriptor 主要用于 @Autowire 注解,在解析 @Autowire 注解的时候,当第一次注入依赖的 bean 实例后,会将该依赖的 bean 的信息封装成 ShortcutDependencyDescriptor ,放到缓存中去,下一次需要依赖注入该 bean 时,可以直接快速的拿到该 bean 实例。

6.查找与所需类型匹配的 bean 实例,这边的返回结果 matchingBeans 的 key 是 beanName,而 value 有两种情况:一种是匹配的 bean 实例,另一种是匹配的 bean 实例的类型,见代码块11详解

7.1 从多个候选者中选出最优的那个,见代码块16详解

代码块11:findAutowireCandidates


protected Map<String, Object> findAutowireCandidates(

String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {

那么如何才能正确的掌握Redis呢?

为了让大家能够在Redis上能够加深,所以这次给大家准备了一些Redis的学习资料,还有一些大厂的面试题,包括以下这些面试题

  • 并发编程面试题汇总

  • JVM面试题汇总

  • Netty常被问到的那些面试题汇总

  • Tomcat面试题整理汇总

  • Mysql面试题汇总

  • Spring源码深度解析

  • Mybatis常见面试题汇总

  • Nginx那些面试题汇总

  • Zookeeper面试题汇总

  • RabbitMQ常见面试题汇总

JVM常频面试:

[外链图片转存中…(img-DG4QnruU-1714870705040)]

Mysql面试题汇总(一)

[外链图片转存中…(img-8RBYyh66-1714870705041)]

Mysql面试题汇总(二)

[外链图片转存中…(img-WxIvmLgc-1714870705041)]

Redis常见面试题汇总(300+题)

[外链图片转存中…(img-bigCFGLt-1714870705042)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值