简介
spring在启动过程中会创建一部分单例的bean,在bean完成实例化后或者用有参构造进行实例化时,会进行属性注入,这是会根据程序的配置构造依赖。
依赖注入的几种方式
spring在进行依赖注入时,主要分为构造函数注入和setter方法(@Autowired放在属性或者setter方法上的)两种,spring在对一个bean初始化时就会开始查找需要的依赖,并提前加载创建需要的依赖完成注入。其次还有一种使用@DependsOn注解,可以在bean加载之前提前创建该注解的依赖。
构造函数注入
在spring创建bean时,首先会找到bean的构造函数,然后通过指定构造函数创建bena的实例,创建完成实例后,再对相关的属性注入。在以上步骤中,如果找到的是有参构造函数,那么spring会先参构造的注入,先创建需要的参数进行注入。代码如下:
1.首先会调用getbean方法创建bean。后面找需要参数也使用getBean方法创建参数。总之spring在创建bean时总是会调用getBean,只不过调用的位置和时机不同。
public void preInstantiateSingletons() throws BeansException {
...
for (String beanName : beanNames) {
...
getBean(beanName);
...
}
}
2.间会经过各种验证,推断构造方法,最后会调用autowireConstructor方法。间方法调用链条:gtBean—>doGetBean—>createBean—->doCreateBean—>createBeanInstance—>autowireConstructor
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
//bean实例化的包装器
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
//存放要使用的构造函数
Constructor<?> constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
//存放要使用的构造函数的参数
Object[] argsToUse = 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);
}
}
//如果构造函数或参数不存在,那么说明继续推断
if (constructorToUse == null || argsToUse == null) {
// Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;
//如果没有候选的构造函数,那么直接找默认的无参构造
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
//是否允许非public的构造方法访问,然后根据反射获取公开或者非公开的构造
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) {
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
mbd.constructorArgumentsResolved = true;
mbd.resolvedConstructorArguments = EMPTY_ARGS;
}
//实例化bean
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
return bw;
}
}
/*
* 没有默认的无参构造,那么需要继续推断构造函数
*
* autowiring为true表示自动注入,有@Autowried注解的构造,或者注入模型为AUTOWIRE_CONSTRUCTOR的就是自动注入
*
* minNrOfArgs记录需要的最少的参数值。有可能有多个候选构造,如果构造函数的参数小于这个值,那么肯定就不会是这个构造函数,直接跳过
* 如果开发者指定了参数,那么就是参数的个数就是该值,没有指定则为0
* */
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
resolvedValues = new ConstructorArgumentValues();
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
// 对候选构造方法进行排序,public的方法排在最前面,都是public的情况下参数个数越多越靠前
AutowireUtils.sortConstructors(candidates);
/*
* 记录构造函数与参数的最小差异值:
* spring会排序遍历所有的构造函数,并且会去找构造函数上的参数,在寻找的过程中会记录每一个构造函数与参数的匹配程度,越匹配的这个差异值就越小
* */
int minTypeDiffWeight = Integer.MAX_VALUE;
/*
* 表示有歧义的构造函数,有可能多个构造函数的差异值一样,就不知道用那个构造函数了,就会放入该队列。再根据是否宽松或严格模式去判断,宽松则取第一个,严格则抛出异常
* */
Set<Constructor<?>> ambiguousConstructors = null;
//记录遍历时,程序抛出的异常
Deque<UnsatisfiedDependencyException> causes = null;
for (Constructor<?> candidate : candidates) {
int parameterCount = candidate.getParameterCount();
//经过多次遍历可能已经找到了需要的构造函数和参数,并且再比较找到的参数数量是否大于本次的,是的话那么后面的不需要再找了
// ,因为是排过序的,后面的参数数量只会小于本次的
if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
break;
}
//如果这个构造函数的参数小于最少需要的构造参数个数值,那么直接略过
if (parameterCount < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
Class<?>[] paramTypes = candidate.getParameterTypes();
/*
* 如果进入到了这里,说明开发者没有指定构造参数。
*
* 那么spring会根据每一个参数类型和名称到容器中取匹配合适的值
* */
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) {
if (logger.isTraceEnabled()) {
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new ArrayDeque<>(1);
}
causes.add(ex);
continue;
}
}
/*
* 如果指定了构造函数的参数,那么一直找到符合指定参数个数的构造函数,并创建一个参数持有器
* */
else {
// Explicit arguments given -> arguments length must match exactly.
if (parameterCount != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
/*
* 下面这段代码是计算构造函数与参数的差异化的值:
* 根据不同的模式(宽松/严格)计算最小差异值
* */
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
//此次计算的差异值比之前的更小,那么就取当前这个,然后重新赋值给minTypeDiffWeight,以便后续遍历使用
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;//这里复制为null,因为找到合适的了,之前即使有歧义的构造函数已经无所谓了
}
//计算出来差异值一样的多个函数表示存在歧义,加入到歧义队列。constructorToUse != null表示至少已经存在一个构造函数,因为两个及以上才会存在歧义
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
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 on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
//严格模式下,不允许存在有歧义的构造函数
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
//如果开发者没有指定参数,且spring找到了参数,那么将参数缓存。(不会缓存开发者指定的参数,因为不知道何时开发者就会换掉指定的参数)
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;
}
autowireConstructor这个方法的大概意思是:根据传入的构造函数集合和显示指定的参数,查找符合条件的构造函数和参数,并创建一个bean的实例。
一般来说显示参数为null,这里会将我们的构造函数集合排序,然后找到推断出来的构造方法,再去找构造函数上的参数
3.createArgumentArray方法创建参数。这个方法的大概意思就是遍历所有的参数集合,一个一个参数的查找,先找bean定义中,没有则在spring容器中找,最后会调用beanFactory.resolveDependency通用处理依赖的方法,一般来说会调用getBean方法创建需要的参数
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] : "");
// Try to find matching constructor argument value, either indexed or generic.
ConstructorArgumentValues.ValueHolder valueHolder = null;
//这个分支表示如果bean定义中设置了参数,就从bean定义中获取
if (resolvedValues != null) {
//先通过索引+类型+名称匹配是否已经存在了参数
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).
//如果没有找到匹配的参数,且不是自动注入的,尝试解析需要类型转换的
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
}
if (valueHolder != null) {
// We found a potential match - let's give it a try.
// Do not consider the same value definition multiple times!
usedValueHolders.add(valueHolder);
Object originalValue = valueHolder.getValue();
Object convertedValue;
if (valueHolder.isConverted()) {
convertedValue = valueHolder.getConvertedValue();
args.preparedArguments[paramIndex] = convertedValue;
}
else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
try {
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
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());
}
Object sourceHolder = valueHolder.getSource();
if (sourceHolder instanceof ConstructorArgumentValues.ValueHolder) {
Object sourceValue = ((ConstructorArgumentValues.ValueHolder) sourceHolder).getValue();
args.resolveNecessary = true;
args.preparedArguments[paramIndex] = sourceValue;
}
}
args.arguments[paramIndex] = convertedValue;
args.rawArguments[paramIndex] = originalValue;
}
//到这表示还没有找到匹配的值,需要自动装配。既然通过构造函数注入,那么肯定是需要明确参数值的,如果找不到,那么就抛出异常。
else {
MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
// No explicit match found: we're either supposed to autowire or
// have to fail creating an argument array for the given constructor.
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 {
//在spring容器中查找对应的类型
Object autowiredArgument = resolveAutowiredArgument(
methodParam, beanName, autowiredBeanNames, converter, fallback);
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = autowiredArgumentMarker;
args.resolveNecessary = true;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
}
}
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
return args;
}
在上述代码中,循环查找每一个参数,最后将参数集合返回,最后在autowireConstructor中拿着构造函数和所需要的参数反射调用,完成bean的实例化。
setter方法注入
紧跟着上一步,bean的实例化之后,spring就会开始对bean的属性进行注入。实例化时可能会注入一部分字段,也有可能部分字段使用了@Autowried注入的,或者@Reource,那么在此时就在这里进行注入。
1.整个过程还是发生在spring的启动过程中的bean的生命周期里。调用链如下:
gtBean—>doGetBean—>createBean—->doCreateBean—>createBeanInstance之后的populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
/*
* 这里自己可以自己实现InstantiationAwareBeanPostProcessors接口,用于修改bean的属性填充,如果返回false表示不需要spring后续填充
*
* */
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
/*
* 就要开始注入属性了。根据注入模型注入bean的属性。
* AUTOWIRE_BY_NAME 通过名称注入
* AUTOWIRE_BY_TYPE 通过类型注入
* AUTOWIRE_CONSTRUCTOR 通过构造函数注入
*
* 一般为0 即AUTOWIRE_NO 表示没有注入模式
*
* */
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
/*
* 这里表示开始属性注入。根据属性的上的注解,分别使用不同的后置处理器来处理
*
* 是否存在实现了InstantiationAwareBeanPostProcessor的处理器。初始化时这里为true,应为有两个是spring自带的内置处理器实现了该接口
* CommonAnnotationBeanPostProcessor后置处理器解析,处理@Resource
* AutowiredAnnotationBeanPostProceoor后置处理器解析,处理@Autowired
*
* 用了@Autowire注解的属性注入就是在这里进行的(AutowiredAnnotationBeanPostProcessor处理器)
*
* */
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {//这里再次调用getPropertyValues()是为了给个默认值
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
在上述代码里可以看到,不同的注解注入的属性由不同的处理器负责,那么看看@Autowried注解的。
2.@Autowried注解是由AutowiredAnnotationBeanPostProcessor处理器来处理依赖的,在这个类中有两个内部类AutowiredMethodElement,AutowiredFieldElement分别对应的setter方法上和字段上使用 @Autowried注入的,由这两个内部类来处理。
方法调用链:populateBean—>postProcessProperties—>metadata.inject
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
element.inject(target, beanName, pvs);
}
}
}
上述方法是把所有的需要注入的属性(不管是方法还是字段),都封装为一个InjectedElement,然后拿到集合开始一个一个调用各自的inject方法(不同的实现类的逻辑不同),方法和字段的调用链为:
- inject—>resolveFieldValue—>resolveFieldValue—>beanFactory.resolveDependency
- inject—>resolveFieldValue—>resolveMethodArguments—>beanFactory.resolveDependency
可以看到不管是字段的还是setter方法的最后也都是调用beanFactory.resolveDependency方法来处理依赖,同上面构造方法注入一致。那么下面来看看beanFactory.resolveDependency方法的具体实现。
resolveDependency方法解析
resolveDependency方法是Spring进行依赖查找的核心 ,用于解析和获取 bean 之间的依赖关系。通常用于处理注入、自动装配、依赖查找等操作。
// Spring 进行依赖查找的核心 ,处理bean所需的依赖,包括属性注入的字段
/**
* @param descriptor 表示依赖的描述符,包括依赖的类型、是否需要按名称解析依赖、是否需要进行嵌套查找等信息。
* @param requestingBeanName 表示请求解析依赖的 bean 的名称。通常在自动装配时使用,用于确定依赖的上下文。
* @param autowiredBeanNames 表示自动装配的 bean 的名称集合。通常在自动装配时使用,用于解决循环依赖等问题。
* @param typeConverter 用于执行类型转换的转换器。通常用于将依赖的值从一种类型转换为另一种类型。
* @return
* @throws BeansException
*/
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 初始化参数名称发现器,用于后续参数名称的解析
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 检查依赖类型是否为 Optional,如果是,创建 Optional 依赖
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
// 检查依赖类型是否为 ObjectFactory 或 ObjectProvider,如果是,创建 DependencyObjectProvider
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
// 检查依赖类型是否为 javaxInjectProviderClass(JSR-330 Provider 类型),如果是,使用 Jsr330Factory 创建依赖 Provider
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
// 使用 AutowireCandidateResolver 获取懒加载代理(如果有的话)
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
// 如果没有懒加载代理,尝试解析依赖
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
通常情况下,在这里最后会调用doResolveDependency方法解析依赖,这里也是解析依赖的最核心方法
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
/*1.尝试快速查找 AutowiredAnnotationBeanPostProcessor.ShortcutDependencyDescriptor实现*/
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//2. 注入指定值,QualifierAnnotationAutowireCandidateResolver解析@Value会用到
Class<?> type = descriptor.getDependencyType();
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);
//el表达式解析
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
//类型转换
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
//3.处理构造参为Collection,map,数组等这样类型的
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//4.正常的注入查找:这里有可能是bean定义,一个实例对象
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
//如果还是没有找到,又必须需要这个依赖,那么抛出异常
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
//记录注入的bean名称,和bean对象实例
String autowiredBeanName;
Object instanceCandidate;
//如果找到多个匹配的,
if (matchingBeans.size() > 1) {
//那么根据 @Primary -> @Priority -> 方法名称或字段名称 权重匹配最合适的
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
//如果找不到,也不是集合或数组的,那么抛出异常
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
//找不到,集合类型的返回null
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;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
//刚好只有一个匹配的,那么就是这个了
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
/*
* 调用getBean从容器中获取bean
*
* 这里如果bean没有实例化会在提前这里实例化
* 可能会存在循环依赖
* */
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
//如果获取bean的实例失败,且是必须依赖的,在这抛出异常
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
上述方法主要作用是根据 DependencyDescriptor 中的信息,解析和获取依赖的 Bean 实例。在解析过程中,它处理了各种情况,包括是否有快捷方式、是否有建议的值、是否有多个候选 Bean、是否需要类型转换、是否需要解析注解、是否满足必需条件等等
总结
综上所述,不管是哪种依赖的注入 ,最后都会调用resolveDependency来处理依赖,只是在不同的位置调用该方法的时机不同