Spring系列-4.2 Bean 的实例化过程
Spring版本:Spring 5.2.9.BUILD-SNAPSHOT
修改过部分源码,但不影响主体流程
概述#
createBeanInstance
根据方法名就知道,就是创建bean
的实例,根据执行bean
使用对应的策略创建新的实例,如,工厂方法,构造函数主动注入、简单初始化。
源码#
createBeanInstance#
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 确认需要创建的bean实例的类可以实例化
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 确保class不为空,并且访问权限是public
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// 判断当前beanDefinition中是否包含实例供应器,此处相当于一个回调方法,利用回调方法来创建bean
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果工厂方法不为空则使用工厂方法初始化策略
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
// 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析
// Shortcut when re-creating the same bean...
// 标记下,防止重复创建同一个bean
boolean resolved = false;
// 是否需要自动装配
boolean autowireNecessary = false;
// 如果没有参数
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 因为一个类可能由多个构造函数,所以需要根据配置文件中配置的参数或传入的参数来确定最终调用的构造函数。
// 因为判断过程会比较,所以spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod字段中。
// 在下次创建相同时直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值获取,避免再次解析
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 有构造参数的或者工厂方法
if (resolved) {
// 构造器有参数
if (autowireNecessary) {
// 构造函数自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
// 从bean后置处理器中为自动装配寻找构造方法, 有且仅有一个有参构造或者有且仅有@Autowired注解构造
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 以下情况符合其一即可进入
// 1、存在可选构造方法
// 2、自动装配模型为构造函数自动装配
// 3、给BeanDefinition中设置了构造参数值
// 4、有参与构造函数参数列表的参数
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
// 找出最合适的默认构造方法
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
// 构造函数自动注入
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 使用默认无参构造函数创建对象,如果没有无参构造且存在多个有参构造且没有@AutoWired注解构造,会报错
return instantiateBean(beanName, mbd);
}
-
判断当前
beanDefinition
中是否包含Supplier
实例供应器,此处相当于一个回调方法,利用回调方法来创建bean`。 -
如果
beanDefinition
中存在factoryMethodName
属性,或者在配置文件中配置了factory-method
,Spring
会尝试使用instantiateUsingFactoryMethod
方法,根据beanDefinition
中的配置生成bean
实例。 -
通过构造函数实例化
bean
obtainFromSupplier#
/**
* 从supplier获取bean
*
* Obtain a bean instance from the given supplier.
* @param instanceSupplier the configured supplier
* @param beanName the corresponding bean name
* @return a BeanWrapper for the new instance
* @since 5.0
* @see #getObjectForBeanInstance
*/
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance;
// 获取原先创建的beanName
String outerBean = this.currentlyCreatedBean.get();
// 用当前作对做替换
this.currentlyCreatedBean.set(beanName);
try {
// 调用supplier的方法
instance = instanceSupplier.get();
}
finally {
if (outerBean != null) {
this.currentlyCreatedBean.set(outerBean);
}
else {
this.currentlyCreatedBean.remove();
}
}
// 如果没有创建对象,默认为NullBean
if (instance == null) {
instance = new NullBean();
}
// 初始化BeanWrapper并返回
BeanWrapper bw = new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}
从supplier
获取bean
,应用场景 : 指定一个用于创建bean
实例的回调,以替代声明式指定的工厂方法。主要是考虑反射调用目标方法不如直接调用目标方法效率高。
instantiateUsingFactoryMethod#
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
// 新建一个BeanWrapperImp实例,用于封装使用工厂方法生成与beanName对应的Bean对象
BeanWrapperImpl bw = new BeanWrapperImpl();
// 初始化实例包装类
this.beanFactory.initBeanWrapper(bw);
// 获取工厂Bean对象,工厂Bean对象的类对象,确定工厂方法是否是静态
// 定义一个用于存放工厂Bean对象的Object
Object factoryBean;
// 定义一个用于存放工厂Bean对象的类对象的Class
Class<?> factoryClass;
// 定义一个表示是静态工厂方法的标记
boolean isStatic;
// 从mbd中获取配置的FactoryBean名
String factoryBeanName = mbd.getFactoryBeanName();
// 如果factoryBeanName不为null
if (factoryBeanName != null) {
// 如果factoryBean名与beanName相同
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// 从bean工厂中获取factoryBeanName所指的factoryBean对象
factoryBean = this.beanFactory.getBean(factoryBeanName);
// 如果mbd配置为单例作用域 且 beanName已经在bean工厂的单例对象的高速缓存Map中
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
// 这个时候意味着Bean工厂中已经有beanName的Bean对象,而这个还要生成多一个Bean名为BeanName的Bean对象,导致了冲突
// 抛出ImplicitlyAppearedSingletonException,
throw new ImplicitlyAppearedSingletonException();
}
// 获取factoryBean的Class对象
factoryClass = factoryBean.getClass();
// 设置isStatic为false,表示不是静态方法
isStatic = false;
}
else {
// It's a static factory method on the bean class.
// 这是bean类上的静态工厂方法
// 如果mbd没有指定bean类
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
// 将factoryBean设为null
factoryBean = null;
// 指定factoryClass引用mbd指定的bean类
factoryClass = mbd.getBeanClass();
// 设置isStatic为true,表示是静态方法
isStatic = true;
}
// 尝试从mbd的缓存属性中获取要使用的工厂方法,要使用的参数值数组
// 声明一个要使用的工厂方法,默认为null
Method factoryMethodToUse = null;
// 声明一个用于存储不同形式的参数值的ArgumentsHolder,默认为null
ArgumentsHolder argsHolderToUse = null;
// 声明一个要使用的参数值数组,默认为null
Object[] argsToUse = null;
// 如果explicitArgs不为null
if (explicitArgs != null) {
// argsToUse就引用explicitArgs
argsToUse = explicitArgs;
}
else {
// 如果没有传
// 声明一个要解析的参数值数组,默认为null
Object[] argsToResolve = null;
// 使用mbd的构造函数字段通用锁进行加锁,以保证线程安全
synchronized (mbd.constructorArgumentLock) {
// 指定factoryMethodToUser引用mbd已解析的构造函数或工厂方法对象
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
// 如果factoryMethodToUser不为null且mbd已解析构造函数参数
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached factory method...
// 找到了缓存的工厂方法
// 指定argsToUser引用mbd完全解析的构造函数参数值
argsToUse = mbd.resolvedConstructorArguments;
// 如果argsToUse为null
if (argsToUse == null) {
// 指定argsToResolve引用mbd部分准备好的构造函数参数值
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
// 如果argsToResolve不为null,即表示mbd还没有完全解析的构造函数参数值
if (argsToResolve != null) {
// 解析缓存在mbd中准备好的参数值,允许在没有此类BeanDefintion的时候回退
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
}
}
// 如果没解析过,就获取factoryClass的用户定义类型,因为此时factoryClass可能是CGLIB动态代理类型,
// 所以要获取用父类的类型。如果工厂方法是唯一的,就是没重载的,就获取解析的工厂方法,如果不为空,就添加到一个不可变列表里,
// 如果为空的话,就要去找出factoryClass的以及父类的所有的方法,进一步找出方法修饰符一致且名字跟工厂方法名字相同的且是bean注解的方法,并放入列表里。
if (factoryMethodToUse == null || argsToUse == null) {
// Need to determine the factory method...
// Try all methods with this name to see if they match the given arguments.
// 获取工厂类的所有候选工厂方法
factoryClass = ClassUtils.getUserClass(factoryClass);
// 定义一个用于存储候选方法的集合
List<Method> candidates = null;
// 如果mbd所配置工厂方法时唯一
if (mbd.isFactoryMethodUnique) {
// 如果factoryMethodToUse为null
if (factoryMethodToUse == null) {
// 获取mbd解析后的工厂方法对象
factoryMethodToUse = mbd.getResolvedFactoryMethod();
}
// 如果factoryMethodToUse不为null
if (factoryMethodToUse != null) {
// Collections.singletonList()返回的是不可变的集合,但是这个长度的集合只有1,可以减少内存空间。但是返回的值依然是Collections的内部实现类,
// 同样没有add的方法,调用add,set方法会报错
// 新建一个不可变,只能存一个对象的集合,将factoryMethodToUse添加进行,然后让candidateList引用该集合
candidates = Collections.singletonList(factoryMethodToUse);
}
}
// 如果candidateList为null
if (candidates == null) {
// 让candidateList引用一个新的ArrayList
candidates = new ArrayList<>();
// 根据mbd的是否允许访问非公共构造函数和方法标记【RootBeanDefinition.isNonPublicAccessAllowed】来获取factoryClass的所有候选方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
// 遍历rawCandidates,元素名为candidate
for (Method candidate : rawCandidates) {
// 如果candidate的修饰符与isStatic一致且candidate有资格作为mdb的工厂方法
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
// 将candidate添加到candidateList中
candidates.add(candidate);
}
}
}
// 候选方法只有一个且没有构造函数时,就直接使用该候选方法生成与beanName对应的Bean对象封装到bw中返回出去
// 如果candidateList只有一个元素且没有传入构造函数值且mbd也没有构造函数参数值
if (candidates.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
// 获取candidateList中唯一的方法
Method uniqueCandidate = candidates.get(0);
// 如果uniqueCandidate是不需要参数
if (uniqueCandidate.getParameterCount() == 0) {
// 让mbd缓存uniqueCandidate【{@link RootBeanDefinition#factoryMethodToIntrospect}】
mbd.factoryMethodToIntrospect = uniqueCandidate;
// 使用mdb的构造函数字段的通用锁【{@link RootBeanDefinition#constructorArgumentLock}】进行加锁以保证线程安全
synchronized (mbd.constructorArgumentLock) {
// 让mbd缓存已解析的构造函数或工厂方法【{@link RootBeanDefinition#resolvedConstructorOrFactoryMethod}】
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
// 让mbd标记构造函数参数已解析【{@link RootBeanDefinition#constructorArgumentsResolved}】
mbd.constructorArgumentsResolved = true;
// 让mbd缓存完全解析的构造函数参数【{@link RootBeanDefinition#resolvedConstructorArguments}】
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
// 使用factoryBean生成的与beanName对应的Bean对象,并将该Bean对象保存到bw中
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
// 将bw返回出去
return bw;
}
}
// 如果有多个工厂方法的话进行排序操作
if (candidates.size() > 1) { // explicitly skip immutable singletonList
candidates.sort(AutowireUtils.EXECUTABLE_COMPARATOR);
}
// ConstructorArgumentValues:构造函数参数值的Holder,通常作为BeanDefinition的一部分,支持构造函数参数列表中特定索引的值
// 以及按类型的通用参数匹配
// 定义一个用于存放解析后的构造函数参数值的ConstructorArgumentValues对象
ConstructorArgumentValues resolvedValues = null;
// 定义一个mbd是否支持使用构造函数进行自动注入的标记
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
// 定义一个最小类型差异权重,默认是Integer最大值
int minTypeDiffWeight = Integer.MAX_VALUE;
// 定义一个存储摸棱两可的工厂方法的Set集合,以用于抛出BeanCreationException时描述异常信息
Set<Method> ambiguousFactoryMethods = null;
// 定义一个最少参数数,默认为0
int minNrOfArgs;
// 如果explicitArgs不为null
if (explicitArgs != null) {
// minNrOfArgs引用explicitArgs的数组长度
minNrOfArgs = explicitArgs.length;
}
else {
// We don't have arguments passed in programmatically, so we need to resolve the
// arguments specified in the constructor arguments held in the bean definition.
// 我们没有以编程方式传递参数,因此我们需要解析BeanDefinition中保存的构造函数参数中指定的参数
// 如果mbd有构造函数参数值
if (mbd.hasConstructorArgumentValues()) {
// 获取mbd的构造函数参数值Holder
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
// 对resolvedValues实例化
resolvedValues = new ConstructorArgumentValues();
// 将cargs解析后值保存到resolveValues中,并让minNrOfArgs引用解析后的最小(索引参数值数+泛型参数值数)
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
else {
// 意味着mbd没有构造函数参数值时,将minNrOfArgs设为0
minNrOfArgs = 0;
}
}
// 定义一个用于UnsatisfiedDependencyException的列表
LinkedList<UnsatisfiedDependencyException> causes = null;
// 遍历candidates,元素名为candidate
for (Method candidate : candidates) {
// 获取参数的个数
int parameterCount = candidate.getParameterCount();
// 如果paramTypes的数组长度大于等于minNrOfArgs
if (parameterCount >= minNrOfArgs) {
// ArgumentsHolder:用于保存参数数组
// 定义一个封装参数数组的ArgumentsHolder对象
ArgumentsHolder argsHolder;
// 获取candidate的参数类型数组
Class<?>[] paramTypes = candidate.getParameterTypes();
// 如果explicitArgs不为null
if (explicitArgs != null) {
// Explicit arguments given -> arguments length must match exactly.
// 给定的显示参数->参数长度必须完全匹配
// 如果paramTypes的长度与explicitArgsd额长度不相等
if (paramTypes.length != explicitArgs.length) {
// 跳过当次循环中剩下的步骤,执行下一次循环。
continue;
}
// 实例化argsHolder,封装explicitArgs到argsHolder
argsHolder = new ArgumentsHolder(explicitArgs);
}
else {
// Resolved constructor arguments: type conversion and/or autowiring necessary.
// 已解析的构造函数参数:类型转换 and/or 自动注入时必须的
try {
// 定义用于保存参数名的数组
String[] paramNames = null;
// 获取beanFactory的参数名发现器
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
// 如果pnd不为null
if (pnd != null) {
// 通过pnd解析candidate的参数名
paramNames = pnd.getParameterNames(candidate);
}
// 将resolvedValues转换成一个封装着参数数组ArgumentsHolder实例,当candidate只有一个时,支持可在抛
// 出没有此类BeanDefinition的异常返回null,而不抛出异常
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
paramTypes, paramNames, candidate, autowiring, candidates.size() == 1);
}
// 捕捉UnsatisfiedDependencyException
catch (UnsatisfiedDependencyException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next overloaded factory method.
// 吞下并尝试下一个重载的工厂方法
// 如果cause为null
if (causes == null) {
// 对cause进行实例化成LinkedList对象
causes = new LinkedList<>();
}
// 将ex添加到causes中
causes.add(ex);
// 跳过本次循环体中余下尚未执行的语句,立即进行下一次的循环
continue;
}
}
// mbd支持的构造函数解析模式,默认使用宽松模式:
// 1. 严格模式如果摸棱两可的构造函数在转换参数时都匹配,则抛出异常
// 2. 宽松模式将使用"最接近类型匹配"的构造函数
// 如果bd支持的构造函数解析模式时宽松模式,引用获取类型差异权重值,否则引用获取Assignabliity权重值
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this factory method if it represents the closest match.
// 如果它表示最接近的匹配项,则选择此工厂方法
// 如果typeDiffWeight小于minTypeDiffWeight
if (typeDiffWeight < minTypeDiffWeight) {
// 让factoryMethodToUser引用candidate
factoryMethodToUse = candidate;
// 让argsHolderToUse引用argsHolder
argsHolderToUse = argsHolder;
// 让argToUse引用argsHolder的经过转换后参数值数组
argsToUse = argsHolder.arguments;
// 让minTypeDiffWeight引用typeDiffWeight
minTypeDiffWeight = typeDiffWeight;
// 将ambiguousFactoryMethods置为null
ambiguousFactoryMethods = null;
}
// Find out about ambiguity: In case of the same type difference weight
// for methods with the same number of parameters, collect such candidates
// and eventually raise an ambiguity exception.
// However, only perform that check in non-lenient constructor resolution mode,
// and explicitly ignore overridden methods (with the same parameter signature).
// 找出歧义:如果具有相同数量参数的方法具有相同的类型差异权重,则收集此类候选想并最终引发歧义异常。
// 但是,仅在非宽松构造函数解析模式下执行该检查,并显示忽略的方法(具有相同的参数签名)
// 如果factoryMethodToUse不为null且typeDiffWeight与minTypeDiffWeight相等
// 且mbd指定了严格模式解析构造函数且paramTypes的数组长度与factoryMethodToUse的参数数组长度相等且
// paramTypes的数组元素与factoryMethodToUse的参数数组元素不相等
else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
!mbd.isLenientConstructorResolution() &&
paramTypes.length == factoryMethodToUse.getParameterCount() &&
!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
// 如果ambiguousFactoryMethods为null
if (ambiguousFactoryMethods == null) {
// 初始化ambiguousFactoryMethods为LinkedHashSet实例
ambiguousFactoryMethods = new LinkedHashSet<>();
// 将factoryMethodToUse添加到ambiguousFactoryMethods中
ambiguousFactoryMethods.add(factoryMethodToUse);
}
// 将candidate添加到ambiguousFactoryMethods中
ambiguousFactoryMethods.add(candidate);
}
}
}
// 整合无法筛选出候选方法或者无法解析出要使用的参数值的情况,抛出BeanCreationException并加以描述
// 如果factoryMethodToUse为null或者argsToUse为null
if (factoryMethodToUse == null || argsToUse == null) {
// 如果causes不为null
if (causes != null) {
// 从cause中移除最新的UnsatisfiedDependencyException
UnsatisfiedDependencyException ex = causes.removeLast();
// 遍历causes,元素为cause
for (Exception cause : causes) {
// 将cause添加到该Bean工厂的抑制异常列表【{@link DefaultSingletonBeanRegistry#suppressedExceptions】中
this.beanFactory.onSuppressedException(cause);
}
// 重新抛出ex
throw ex;
}
// 定义一个用于存放参数类型的简单类名的ArrayList对象,长度为minNrOfArgs
List<String> argTypes = new ArrayList<>(minNrOfArgs);
// 如果explicitArgs不为null
if (explicitArgs != null) {
// 遍历explicitArgs.元素为arg
for (Object arg : explicitArgs) {
// 如果arg不为null,将arg的简单类名添加到argTypes中;否则将"null"添加到argTypes中
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
}
}
// 如果resolvedValues不为null
else if (resolvedValues != null) {
// 定义一个用于存放resolvedValues的泛型参数值和方法参数值的LinkedHashSet对象
Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
// 将resolvedValues的方法参数值添加到valueHolders中
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
// 将resolvedValues的泛型参数值添加到valueHolders中
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
// 遍历valueHolders,元素为value
for (ValueHolder value : valueHolders) {
// 如果value的参数类型不为null,就获取该参数类型的简单类名;否则(如果value的参数值不为null,即获取该参数值的简单类名;否则为"null")
String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
// 将argType添加到argTypes中
argTypes.add(argType);
}
}
// 将argType转换成字符串,以","隔开元素.用于描述Bean创建异常
String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
// 抛出BeanCreationException:找不到匹配的工厂方法:工厂Bean'mbd.getFactoryBeanName()';工厂方法
// 'mbd.getFactoryMethodName()(argDesc)'.检查是否存在具体指定名称和参数的方法,并且该方法时静态/非静态的.
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"No matching factory method found: " +
(mbd.getFactoryBeanName() != null ?
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
"Check that a method with the specified name " +
(minNrOfArgs > 0 ? "and arguments " : "") +
"exists and that it is " +
(isStatic ? "static" : "non-static") + ".");
}
// 如果factoryMethodToUse时无返回值方法
else if (void.class == factoryMethodToUse.getReturnType()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid factory method '" + mbd.getFactoryMethodName() +
"': needs to have a non-void return type!");
}
// 如果ambiguousFactoryMethods不为null
else if (ambiguousFactoryMethods != null) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous factory method matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousFactoryMethods);
}
// 将筛选出来的工厂方法和解析出来的参数值缓存到mdb中
// 如果explicitArgs为null且argsHolderToUser不为null
if (explicitArgs == null && argsHolderToUse != null) {
// 让mbd的唯一方法候选【{@link RootBeanDefinition#factoryMethodToIntrospect}】引用factoryMethodToUse
mbd.factoryMethodToIntrospect = factoryMethodToUse;
// 将argsHolderToUse所得到的参数值属性缓存到mbd对应的属性中
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
}
}
// 使用factoryBean生成与beanName对应的Bean对象,并将该Bean对象保存到bw中
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
// 将bw返回出去
return bw;
}
-
在
xml
配置中,可以使用factory-bean
和factory-method
两个标签可以指定一个类中的方法,Spring
会将这个指定的方法的返回值作为bean
返回(如果方法是静态方法,则可以不创建factorybean
就直接调用,否则需要先将factorybean
注入到Spring
中)。 -
对
@Bean
注解的解析。在ConfigurationClassPostProcessor
后置处理器中,会对被@Bean
注解修饰的方法进行解析,生成一个ConfigurationClassBeanDefinition
的BeanDefinition
。此时BeanDefinition
的factoryMethodName
正是@Bean
修饰的方法本身。所以这里会调用instantiateUsingFactoryMethod
方法。通过回调的方式调用@Bean
修饰的方法。并将返回结果注入到Spring
容器中。
构造函数实例化#
这里代码判断逻辑太长,简述一下不贴每个方法的源码了:由于一个bean
可能会存在多个构造函数,这时候Spring
会根据参数列表的来判断使用哪个构造函数进行实例化。但是判断过程比较消耗性能,所以Spring
将判断好的构造函数缓存到RootBeanDefinition
中,如果不存在缓存则进行构造函数的筛选并缓存解析结果。
// 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
// 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析
// Shortcut when re-creating the same bean...
// 标记下,防止重复创建同一个bean
boolean resolved = false;
// 是否需要自动装配
boolean autowireNecessary = false;
// 如果没有参数
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 因为一个类可能由多个构造函数,所以需要根据配置文件中配置的参数或传入的参数来确定最终调用的构造函数。
// 因为判断过程会比较,所以spring会将解析、确定好的构造函数缓存到BeanDefinition中的resolvedConstructorOrFactoryMethod字段中。
// 在下次创建相同时直接从RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod缓存的值获取,避免再次解析
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 有构造参数的或者工厂方法
if (resolved) {
// 构造器有参数
if (autowireNecessary) {
// 构造函数自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
// 从bean后置处理器中为自动装配寻找构造方法, 有且仅有一个有参构造或者有且仅有@Autowired注解构造
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 以下情况符合其一即可进入
// 1、存在可选构造方法
// 2、自动装配模型为构造函数自动装配
// 3、给BeanDefinition中设置了构造参数值
// 4、有参与构造函数参数列表的参数
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
// 找出最合适的默认构造方法
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
// 构造函数自动注入
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 使用默认无参构造函数创建对象,如果没有无参构造且存在多个有参构造且没有@AutoWired注解构造,会报错
return instantiateBean(beanName, mbd);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了