标签:rmi 获取对象 doc cut 还需要 else user ace getbean
目录
Spring 核心编程思想目录:https://www.cnblogs.com/binarylei/p/12290153.html
特别声明: Bean 完整创建过程,包括实例化、依赖注入、初始化阶段 。本文中 Bean 实例化指的是 Bean 对象的创建的第一阶段 - 实例化,不包括之后的属性注入、初始化。为了避免混淆,在此做一个约定,创建阶段指完整的对象创建过程,实例化阶段则单指第一阶段。Spring 构造器注入或工厂注入也是在实例化过程中完成的,之于第二个依赖注入指的是其它的所有注入方式,如 Settter 注入,字段注入等。
Bean 实例化大致可以分为以下场景:
本文重点分析以下方法:
beanFactory#instantiateUsingFactoryMethod:一般表示注解驱动( @Bean 注册),工厂方法实例化。委托给 ConstructorResolver#instantiateUsingFactoryMethod。
Bean 完整的创建过程,包括 Bean 实例化、属性注入、初始化全部操作。本文重点关注实例过程 createBeanInstance。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd,
final @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
// 1. 缓存的提前初始化的FactoryBean,为什么会提前初始化。
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 2. 实例化Bean,构造器注入或工厂方法注入
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 3. 属性注入、初始化 ...
Object exposedObject = bean;
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
...
}
说明: 我们重点说一下为什么会在缓存中获取到提前部分初始化的 FactoryBean?
很明显这些 factoryBean 实例还需要进行属性注入、初始化等操作。我们知道,Spring 在提取对象类型时,FactoryBean 需要调用其 getObjectType 方法,此时就需要初始化 factoryBean 实例,但 Spring 为了减少提前初始化 Bean 产生的问题,只会将 factoryBean 提前实例化后缓存到 factoryBeanInstanceCache,当真正需要使用到 factoryBean 才进行完整的创建。事实上,只要我们进行依赖注入,调用 beanFactory#isTypeMatch 匹配对象类型,就会遍历所有注册的 beanDefinitionNames,从而实例化所有的 factoryBean 到 factoryBeanInstanceCache 中。
这就是 factoryBeanInstanceCache 中 factoryBean 实例的由来,具体见方法见 beanFactory#getSingletonFactoryBeanForTypeCheck,最终其实也是调用 beanFactory#createBeanInstance 方法。
createBeanInstance 方法用于 Bean 对象的实例化,包括工厂方法创建和构造器创建两种。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 1.1 确保此时beanClassName已经加载,当然注解驱动时不会设置beanClassName属性
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 1.2 校验beanClass允许访问
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException();
}
// 2. Supplier创建对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// ========= 工厂方法实例化 =========
// 3. 工厂方法实例化,包括实例化工厂和静态工厂
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// ========= 构造器实例化 =========
// 4. 快速实例化对象,所谓的快速实例化,实际上是说使用缓存
boolean resolved = false;
boolean autowireNecessary = false;
// 4.1 args: 外部化参数,只能当无外部参数时才使用缓存。不推荐使用外部化参数
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 4.2 是否使用缓存,其中autowireNecessary表示是否使用有参构造器
// 无参时肯定不会解析,为false。有参时会解析,为true
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 4.3 使用缓存,其中autowireNecessary表示是否使用有参构造器
if (resolved) {
if (autowireNecessary) {
// 4.4 有参构造器实例化
return autowireConstructor(beanName, mbd, null, null);
} else {
// 4.5 无参构造器实例化
return instantiateBean(beanName, mbd);
}
}
// 5. 到此,只能老老实实的解析,当然解析后会将解析后的构造器或参数缓存起来
// 5.1 是否指定了构造器,ibp#determineCandidateConstructors
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 5.2 构造器实例化
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 5.3 不用管,默认都是 null。
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 5.4 无参构造器实例化
return instantiateBean(beanName, mbd);
}
说明: createBeanInstance 方法在 bd.beanClass 校验后进行对象实例化,而 Supplier 实例化比较简单,工厂方法实例化又全部委托给了 instantiateUsingFactoryMethod 方法,基本上主要的功能就是,判断如何使用构造器实例化对象。
<bean id="beanA" class="com.binarylei.spring.ioc.BeanA" autowire="constructor"/>
。Spring 在对象实例化上进行了抽象,提供了 InstantiationStrategy 接口用于实例对象,两个实现类 SimpleInstantiationStrategy 和 CglibSubclassingInstantiationStrategy。
Spring 默认的实例化策略是 CglibSubclassingInstantiationStrategy,该类是为了解决 <replaced-method> 或 <lookup-method> 标签,在这种情况下,必须进行字节码提升才能实例化对象。通常我们不会用到这些标签,本文只会介绍常规的实例化方法,直接调用反射实例化对象,即其父类 SimpleInstantiationStrategy。
InstantiationStrategy 提供了三个方法,分别用于实例化无参构造器,有参构造器,工厂方法。
// 1. 无参构造器实例化
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner);
throws BeansException;
// 2. 有参构造器实例化
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
Constructor<?> ctor, Object... args) throws BeansException;
// 3. 工厂方法实例化
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
Object factoryBean, Method factoryMethod, Object... args) throws BeansException;
说明: SimpleInstantiationStrategy 实现都非常简单,无非是通过 Java 反射实例化对象。
注意:无参构造器是会缓存 bd.resolvedConstructorOrFactoryMethod。
无参实例化 instantiateBean 方法,本质是直接获取对象的默认构造器,通过反射创建对象,也就是调用 instantiationStrategy.instantiate 方法。
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
// 1. 调用无参构造器实例化对象
Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
// 2. 配置bw的类型转换器,依赖注入时可能需要对注入的属性值进行类型转换
initBeanWrapper(bw);
return bw;
}
autowireConstructor 和 instantiateUsingFactoryMethod 方法其实没有本质的区别,都是通过参数注入。autowireConstructor 通过构造器实例化,instantiateUsingFactoryMethod 通过特定的工厂方法实例化,如果将构造方法当作一种特殊的方法,那么这两种注入方式没有本质的区别。事实上,Spring 也是将这两种注入方式统一进行处理的。
autowireConstructor:传统方式,通过构造器实例化。委托给 ConstructorResolver#autowireConstructor。
instantiateUsingFactoryMethod:一般表示注解驱动( @Bean 注册),通过工厂方法实例化。委托给 ConstructorResolver#instantiateUsingFactoryMethod。
本文重点分析构造器注入 autowireConstructor 方法,了解构造器注入后,工厂注入基本上如出一辙。无论是构造器注入还是工厂方法注入都会面临如下问题:
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
// 1. 使用缓存,快速实例化对象
Constructor<?> constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
ArgumentsHolder argsToUse = mbd.resolvedConstructorArguments;
// 非缓存,进行参数匹配
if (constructorToUse == null || argsToUse == null) {
// 2. (非缓存)匹配无参构造器
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
return ...
}
// 3. (非缓存)匹配有参构造器
for (Constructor<?> candidate : candidates) {
}
}
return bw;
}
说明: 构造器实例化对象,代码比较长。我会将其拆开,大致分为缓存匹配、无参构造器匹配,有参构造器匹配三步分。
只要对象实例化后,bd 就会缓存其构造方法或参数等信息用于快速实例化对象。缓存这一块比较简单,重要的弄清楚这些缓存变量的含义,以及什么时候缓存的?
if (explicitArgs != null) {
argsToUse = explicitArgs;
} else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
}
}
说明: 可以很清楚的看到外部化参数没有使用缓存,每次都需要重新解析。至于参数的解析 resolvePreparedArguments 会在下方进行分析。
无参构造器匹配也很简单,如果没有指定构造器,则对所有的构造器进行匹配。当只有一个无参构造器,且无论是外部化参数或配置参数都为空时,则使用无参构造器。
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
Constructor<?> uniqueCandidate = candidates[0];
if (uniqueCandidate.getParameterCount() == 0) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
说明: 无参构造器解析后,会缓存所有的变量,不会再次解析。最复杂的是有参构造器的解析。
有参构造器匹配比较复杂,但也是有迹可循的:
(1)实际参数解析
对于外部化参数就不多说了,我们重点说一下绝大多数场景,默认配置参数。首先,解析已有的配置参数;其次,根据构造器参数类型和参数名称从 Spring IoC 容器中解析剩余的参数。如果能成功解析,则命中该构造器。
// autowiring表示是否允许从 Spring IoC 容器查找依赖
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;
// 1.1 外部化参数,不需要解析
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
// 1.2 默认配置参数,先解析已有的配置参数
} else {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) {
int parameterCount = candidate.getParameterCount();
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
break;
}
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes();
// 1.3 默认配置参数,如果配置参数不足,从Spring IoC中继续解析参数。如果能解析则匹配成功
if (resolvedValues != null) {
try {
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
} catch (UnsatisfiedDependencyException ex) {
causes.add(ex);
continue;
}
// 1.4 外部化参数,只需要参数个数相等即可。此时resolvedValues=null
} else {
if (parameterCount != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
...
}
说明: 根据实际的参数解析匹配可用的构造器。
(2)权值计算
权重越小优先级越高。如果无法匹配或有多个权重相同的构造器,则抛出异常。constructorToUse 匹配
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 权重最高的构造器
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
// 多个权重最高的构造器
} else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
说明: constructorToUse 表示权重最高的构造器,ambiguousConstructors 表示有多个权重最高的构造器。如果没有匹配的构造器(constructorToUse=null)或有多个权重相等的构造器(ambiguousConstructors!=null)都需要抛出异常。下面我们看一下权重的计算,以 getAssignabilityWeight 为例,权重值越小优先级越高。
// paramTypes 表示构造器或方法参数类型列表
public int getAssignabilityWeight(Class<?>[] paramTypes) {
// 1. arguments表示解析后的参数
for (int i = 0; i < paramTypes.length; i++) {
if (!ClassUtils.isAssignableValue(paramTypes[i], this.arguments[i])) {
return Integer.MAX_VALUE;
}
}
// 2. arguments表示解析前的参数,如配置参数
for (int i = 0; i < paramTypes.length; i++) {
if (!ClassUtils.isAssignableValue(paramTypes[i], this.rawArguments[i])) {
return Integer.MAX_VALUE - 512;
}
}
return Integer.MAX_VALUE - 1024;
}
(3)实例化对象
// 1. 缓存解析后的构造器和参数
if (explicitArgs == null && argsHolderToUse != null) {
argsHolderToUse.storeCache(mbd, constructorToUse);
}
// 2. 调用InstantiationStrategy实例化参数
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
return bw;
说明: 在构造器实例化对象开始前,第一步就是从 bd 缓存中快速实例化对象。其中无参构造器已经在匹配无参构造器时缓存,此时需要缓存有参构造器匹配的变量。
public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {
synchronized (mbd.constructorArgumentLock) {
mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
mbd.constructorArgumentsResolved = true;
if (this.resolveNecessary) {
mbd.preparedConstructorArguments = this.preparedArguments;
} else {
mbd.resolvedConstructorArguments = this.arguments;
}
}
}
在 ArgumentsHolder 对象中有三个变量,都表示参数:
arguments:已经解析后的参数,不需要再进行解析,直接可以注入。
preparedArguments:已部分解析后的参数,这个主要是用来解析注入的实际参数。
rawArguments:原始的参数,这个主要是用来计算构造器的权重。
到目前为止,ConstructorResolver#autowireConstructor 构造器实例化已经分析完毕,autowireConstructor 方法最主要的两个功能就是解析参数,匹配构造器。构造器的匹配我们已经分析过了,接下为是遗留下来的参数解析。
ConstructorResolver 提供了以下方法进行参数解析:
resolveConstructorArguments 方法解析默认的配置参数 mbd.constructorArgumentValues。
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
int minNrOfArgs = cargs.getArgumentCount();
for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
if (valueHolder.isConverted()) {
resolvedValues.addIndexedArgumentValue(index, valueHolder);
} else {
// 核心代码就这么一句,将参数解析全部委托给valueResolver
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
ConstructorArgumentValues.ValueHolder resolvedValueHolder =
new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
resolvedValueHolder.setSource(valueHolder);
resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
}
}
// 泛型参数解析 ...
return minNrOfArgs;
}
说明: resolveConstructorArguments 方法的核心代码就一句,valueResolver.resolveValueIfNecessary。看到 BeanDefinitionValueResolver 你是否会感到很熟悉呢?在 setter 等注入时,调用 beanFactory#applyPropertyValues 方法也需要解析 mbd.pvs 参数,同样也会用到 valueResolver.resolveValueIfNecessary 来解析配置参数,不管是那种注入方式,参数的解析都是一样的。
createArgumentArray 方法很长,其实逻辑反而并不复杂,遍历构造器的所有参数,先到 resolveConstructorArguments 方法已经解析过的参数中查找参数,如果查找到就使用配置的参数。当然如果查找不到,这时就判断是否允许自行注入,如果允许,则从 Spring IoC 容器中查找依赖,即调用 beanFactory#resolveDependency 方法。
/**
* @param resolvedValues 表示bd.constructorArgumentValues中已经解析的参数
* @param paramTypes 表示当前的构造器或方法的参数类型列表
* @param paramNames 方法的参数名称
* @param executable 方法或构造器
* @param autowiring 是否采用构造器自动注入,如果是则会从Spring IoC容器中查找参数
* @param fallback 如果已经有多个构造器或方法匹配,则fallback=false
*/
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, @Nullable ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class<?>[] paramTypes, @Nullable String[] paramNames, Executable executable,
boolean autowiring, boolean fallback) throws UnsatisfiedDependencyException {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
Class<?> paramType = paramTypes[paramIndex];
String paramName = (paramNames != null ? paramNames[paramIndex] : "");
// 1. 从默认的配置参数中查找参数
ConstructorArgumentValues.ValueHolder valueHolder = null;
if (resolvedValues != null) {
// 1.1 查找已经有参数,可以根据参数的索引或名称查找
valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// 1.2 如果不是自动注入,则要想方设法查找参数,因为自动注入还可以从容器中查找参数
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
// 2. 已经从配置该参数,这部分代码省略
if (valueHolder != null) {
...
// 3. 没有配置该参数,尝试从Spring IoC容器中查找
} else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
if (!autowiring) {
throw new UnsatisfiedDependencyException();
}
// 3.1 核心代码,调用 beanFactory#resolveDependency
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
// 3.2 自动注入标记位
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
}
}
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
}
return args;
}
说明: 对于构造器中的参数,如果在配置参数中命中,使用配置的参数。对于没有命中的参数,如果允许自动注入,则调用 beanFactory#resolveDependency 从容器中查找。
resolvePreparedArguments 方法是对 mbd.preparedConstructorArguments 中还需要解析的参数调用 BeanDefinitionValueResolver#resolveValueIfNecessary 进行解析。
private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, Executable executable, Object[] argsToResolve, boolean fallback) {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
Class<?>[] paramTypes = executable.getParameterTypes();
Object[] resolvedArgs = new Object[argsToResolve.length];
for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
Object argValue = argsToResolve[argIndex];
MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
// createArgumentArray 方法设置的自动注入标记
if (argValue == autowiredArgumentMarker) {
argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, fallback);
} else if (argValue instanceof BeanMetadataElement) {
argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
} else if (argValue instanceof String) {
argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
}
Class<?> paramType = paramTypes[argIndex];
resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
}
return resolvedArgs;
}
说明: 核心就是 BeanDefinitionValueResolver#resolveValueIfNecessary,其实所以的类型注入最终都逃不离 beanFactory#resolveDependency 这个最基础的方法,而这个方法的核心是 Spring 的类型自省。
其实也了解了构造器实例化 autowireConstructor 之后,instantiateUsingFactoryMethod 方法基本大同小异。同样是匹配工厂方法,解析参数。
每天用心记录一点点。内容也许不重要,但习惯很重要!
标签:rmi 获取对象 doc cut 还需要 else user ace getbean
原文地址:https://www.cnblogs.com/binarylei/p/12337123.html