Spring中Autowired原理

1. 构造方法参数Autowire

  • BeanClass可以在构造方法上标注@Autowired注解,Spring在创建Bean实例时将自动为其注入依赖参数;
  • Spring会优先使用标注@Autowired注解的构造方法;
  • 当一个构造方法标注了@Autowired注解且required=true时,其余构造方法不允许再标注@Autowired注解;
  • 当多个构造方法标注了@Autowired注解且required=false时,它们会成为候选者,Spring将选择具有最多依赖项的构造方法;
  • 如果没有候选者可以满足,Spring将使用默认的无参构造方法(如果存在);
  • 如果Class有多个含参构造方法,且都没有标注@Autowired注解,此时在创建Bean时会抛错。

1.1. Spring创建Bean实例

创建Bean实例在AbstractAutowireCapableBeanFactory类的createBeanInstance方法:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {// Make sure bean class is actually resolved at this point.Class<?> beanClass = resolveBeanClass(mbd, beanName);// public和access判断,略Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}// 使用工厂创建Bean实例,@Bean注解标注的方法会使用这种方式创建Bean实例// 后续有章节进行分析if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}// Shortcut when re-creating the same bean...boolean resolved = false;boolean autowireNecessary = false;if (args == null) {synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}if (resolved) {if (autowireNecessary) {return autowireConstructor(beanName, mbd, null, null);} else {return instantiateBean(beanName, mbd);}}// 获取候选的构造方法Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {// 使用构造方法创建Bean实例return autowireConstructor(beanName, mbd, ctors, args);}// 此处通过RootBeanDefinition获取候选的构造方法然后创建Bean实例,和上面基本一致ctors = mbd.getPreferredConstructors();if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);}// 使用默认构造方法创建Bean实例return instantiateBean(beanName, mbd);
}

1.2. 获取候选的构造方法集

public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)throws BeanCreationException {// Let's check for lookup methods here...// 略// Quick check on the concurrent map first, with minimal locking.Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);if (candidateConstructors == null) {// Fully synchronized resolution now...synchronized (this.candidateConstructorsCache) {candidateConstructors = this.candidateConstructorsCache.get(beanClass);if (candidateConstructors == null) {Constructor<?>[] rawCandidates;try {// 使用java反射获取声明了的所有构造方法rawCandidates = beanClass.getDeclaredConstructors();} catch (Throwable ex) {throw new BeanCreationException(beanName,"Resolution of declared constructors on bean Class [" + beanClass.getName() +"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);}List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);// 标注@Autowired注解且required=true的构造方法Constructor<?> requiredConstructor = null;// 默认的无参构造方法Constructor<?> defaultConstructor = null;// nullConstructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);int nonSyntheticConstructors = 0;for (Constructor<?> candidate : rawCandidates) {if (!candidate.isSynthetic()) {nonSyntheticConstructors++;} else if (primaryConstructor != null) {continue;}// 在构造方法上查找@Autowired注解MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);if (ann != null) {// 如果之前已经找到了requiredConstructor则抛错if (requiredConstructor != null) {throw new BeanCreationException(beanName,"Invalid autowire-marked constructor: " + candidate +". Found constructor with 'required' Autowired annotation already: " +requiredConstructor);}boolean required = determineRequiredStatus(ann);// 构造方法标注@Autowired注解且required=trueif (required) {if (!candidates.isEmpty()) {throw new BeanCreationException(beanName,"Invalid autowire-marked constructors: " + candidates +". Found constructor with 'required' Autowired annotation: " +candidate);}requiredConstructor = candidate;}// 将构造方法添加到candidates集candidates.add(candidate);} else if (candidate.getParameterCount() == 0) {defaultConstructor = candidate;}}if (!candidates.isEmpty()) {// 把默认无参构造方法添加到candidates集if (requiredConstructor == null) {if (defaultConstructor != null) {candidates.add(defaultConstructor);}}candidateConstructors = candidates.toArray(new Constructor<?>[0]);} else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {// 当candidates为空时,即所有构造方法都没有标注@Autowired注解// 且只有一个构造方法时,默认使用这个构造方法candidateConstructors = new Constructor<?>[] {rawCandidates[0]};} else {candidateConstructors = new Constructor<?>[0];}// 维护缓存this.candidateConstructorsCache.put(beanClass, candidateConstructors);}}}return (candidateConstructors.length > 0 ? candidateConstructors : null);
}

1.3. 使用构造方法创建Bean实例

autowireConstructor(beanName, mbd, ctors, args);

autowireConstructor方法:

protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,Constructor<?>[] chosenCtors, Object[] explicitArgs) {BeanWrapperImpl bw = new BeanWrapperImpl();this.beanFactory.initBeanWrapper(bw);Constructor<?> constructorToUse = null;ArgumentsHolder argsHolderToUse = null;Object[] argsToUse = null;// explicitArgs == nullif (explicitArgs != null) {argsToUse = explicitArgs;} else {Object[] argsToResolve = null;// 获取mbd中缓存的构造方法和参数并用其创建对象,此处不详细分析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);}}// 这里从候选构造方法集选择一个最佳构造方法if (constructorToUse == null || argsToUse == null) {Constructor<?>[] candidates = chosenCtors;if (candidates == null) {// 使用反射获取声明的所有构造方法}// 只有一个无参的默认构造方法// 1. 将其放入mbd缓存起来// 2. 使用这个构造方法创建Bean实例并返回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;}}// Need to resolve the constructor.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);}// 排序,参数多的排在前面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();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) {// Swallow and try next constructor.if (causes == null) {causes = new LinkedList<>();}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.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);}}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");} else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Ambiguous constructor matches found in bean");}if (explicitArgs == null && argsHolderToUse != null) {argsHolderToUse.storeCache(mbd, constructorToUse);}}// 使用选择到的构造方法创建Bean实例bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));return bw;
}

2. 字段和setter方法参数Autowire

2.1. 创建Bean流程

Bean实例化流程分析时,我们了解到在AbstractAutowireCapableBeanFactorydoCreateBean方法会创建Bean实例并进行初始化和依赖注入:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {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.boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.Object exposedObject = bean;try {// 依赖注入populateBean(beanName, mbd, instanceWrapper);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);}}// 略return exposedObject;
}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;}}// 调用InstantiationAwareBeanPostProcessor处理器postProcessAfterInstantiation方法if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}}}PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);// 自动注入setter// AUTOWIRE_BY_NAME和AUTOWIRE_BY_TYPE两种模式会进入分支进行处理// 默认AUTOWIRE_NO模式// 此处仅处理有setter方法的属性int resolvedAutowireMode = mbd.getResolvedAutowireMode();if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// 使用属性名称注入if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// 使用属性类型注入if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;// 此处调用InstantiationAwareBeanPostProcessor处理器postProcessProperties方法// AutowiredAnnotationBeanPostProcessor实现类中有依赖注入的逻辑PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.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);}
}

2.2. AutowiredAnnotationBeanPostProcessor处理器

此处理器为标注了@Autowired的字段和方法进行自动注入。

也会处理@Value注解,这个暂时不做分析。

2.2.1. postProcessProperties方法
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {// 获取到标注了@Autowired注解的字段和方法InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);try {// 为字段和方法做依赖注入metadata.inject(bean, beanName, pvs);} catch (BeanCreationException ex) {throw ex;} catch (Throwable ex) {throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);}return pvs;
}private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {// Fall back to class name as cache key, for backwards compatibility with custom callers.String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());// Quick check on the concurrent map first, with minimal locking.InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);if (InjectionMetadata.needsRefresh(metadata, clazz)) {synchronized (this.injectionMetadataCache) {metadata = this.injectionMetadataCache.get(cacheKey);if (InjectionMetadata.needsRefresh(metadata, clazz)) {if (metadata != null) {metadata.clear(pvs);}// 获取到标注了@Autowired注解的字段和方法metadata = buildAutowiringMetadata(clazz);this.injectionMetadataCache.put(cacheKey, metadata);}}}return metadata;
}private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {return InjectionMetadata.EMPTY;}List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;do {final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();ReflectionUtils.doWithLocalFields(targetClass, field -> {\// 获取字段上标注的@Autowired和@Value注解MergedAnnotation<?> ann = findAutowiredAnnotation(field);if (ann != null) {// 静态字段不处理if (Modifier.isStatic(field.getModifiers())) {return;}boolean required = determineRequiredStatus(ann);// 添加到InjectedElement集currElements.add(new AutowiredFieldElement(field, required));}});ReflectionUtils.doWithLocalMethods(targetClass, method -> {Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {return;}MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {// 静态方法不处理if (Modifier.isStatic(method.getModifiers())) {return;}boolean required = determineRequiredStatus(ann);PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);currElements.add(new AutowiredMethodElement(method, required, pd));}});elements.addAll(0, currElements);targetClass = targetClass.getSuperclass();} while (targetClass != null && targetClass != Object.class);return InjectionMetadata.forElements(elements, clazz);
}

依赖注入:

metadata.inject(bean, beanName, pvs);

inject的实现在InjectionMetadata类:

public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {Collection<InjectedElement> checkedElements = this.checkedElements;Collection<InjectedElement> elementsToIterate =(checkedElements != null ? checkedElements : this.injectedElements);if (!elementsToIterate.isEmpty()) {for (InjectedElement element : elementsToIterate) {// 调用InjectedElement的inject方法为字段或方法注入依赖// 从之前的方法可以知道,element是AutowiredFieldElement或AutowiredMethodElement对象element.inject(target, beanName, pvs);}}
}
2.2.2. AutowiredFieldElement

AutowiredFieldElementinject方法:

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {Field field = (Field) this.member;Object value;if (this.cached) {value = resolvedCachedArgument(beanName, this.cachedFieldValue);} else {DependencyDescriptor desc = new DependencyDescriptor(field, this.required);desc.setContainingClass(bean.getClass());Set<String> autowiredBeanNames = new LinkedHashSet<>(1);TypeConverter typeConverter = beanFactory.getTypeConverter();try {// 使用beanFactory从容器里面获取依赖的Beanvalue = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);} catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);}synchronized (this) {if (!this.cached) {Object cachedFieldValue = null;if (value != null || this.required) {cachedFieldValue = desc;registerDependentBeans(beanName, autowiredBeanNames);if (autowiredBeanNames.size() == 1) {String autowiredBeanName = autowiredBeanNames.iterator().next();if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());}}}this.cachedFieldValue = cachedFieldValue;this.cached = true;}}}if (value != null) {// 为字段设置值ReflectionUtils.makeAccessible(field);field.set(bean, value);}
}

从容器获取依赖的Bean实例:

public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());if (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);} else if (ObjectFactory.class == descriptor.getDependencyType() ||ObjectProvider.class == descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);} else if (javaxInjectProviderClass == descriptor.getDependencyType()) {return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);} else {// 此处处理Lazy注解,使用代理// 返回一个代理对象,在拦截方法时从容器里面获取真实的Bean实例再调用目标方法// 只是创建代理,不做展开分析Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result == null) {// 从容器里面获取依赖的Bean实例result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}
}public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);try {Object shortcut = descriptor.resolveShortcut(this);if (shortcut != null) {return shortcut;}Class<?> type = descriptor.getDependencyType();// 为@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());try {return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());} catch (UnsupportedOperationException ex) {return (descriptor.getField() != null ?converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));}}// 数组、集合、MapObject multipleBeans =resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);if (multipleBeans != null) {return multipleBeans;}// 根据依赖的数据类型从容器里面查找符合的Bean// BeanName -> BeanClass的映射Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);if (matchingBeans.isEmpty()) {if (isRequired(descriptor)) {// 没有找到抛出NoSuchBeanDefinitionException异常raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}return null;}String autowiredBeanName;Object instanceCandidate;if (matchingBeans.size() > 1) {// 当找到多个类型符合的Bean需要选择一个最合适的// 1. 找标注了@Primary注解的Bean// 2. 找javax.annotation.Priority配置最高的Bean// 3. 找beanName与字段名相符或bean别名与字段名相符的BeanautowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);if (autowiredBeanName == null) {if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);} else {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);}if (instanceCandidate instanceof Class) {// 使用beanName到容器里面找Bean实例instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);}Object result = instanceCandidate;if (result instanceof NullBean) {if (isRequired(descriptor)) {// 没有找到抛出NoSuchBeanDefinitionException异常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);}
}
2.2.3. AutowiredMethodElement

AutowiredMethodElement方法:

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {// pvs包含就不处理if (checkPropertySkipping(pvs)) {return;}Method method = (Method) this.member;Object[] arguments;if (this.cached) {arguments = resolveCachedArguments(beanName);} else {// 从容器查找依赖的Beanint argumentCount = method.getParameterCount();arguments = new Object[argumentCount];DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);TypeConverter typeConverter = beanFactory.getTypeConverter();for (int i = 0; i < arguments.length; i++) {MethodParameter methodParam = new MethodParameter(method, i);DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);currDesc.setContainingClass(bean.getClass());descriptors[i] = currDesc;try {Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);if (arg == null && !this.required) {arguments = null;break;}arguments[i] = arg;} catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);}}synchronized (this) {if (!this.cached) {if (arguments != null) {DependencyDescriptor[] cachedMethodArguments =Arrays.copyOf(descriptors, arguments.length);registerDependentBeans(beanName, autowiredBeans);if (autowiredBeans.size() == argumentCount) {Iterator<String> it = autowiredBeans.iterator();Class<?>[] paramTypes = method.getParameterTypes();for (int i = 0; i < paramTypes.length; i++) {String autowiredBeanName = it.next();if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {cachedMethodArguments[i] = new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName, paramTypes[i]);}}}this.cachedMethodArguments = cachedMethodArguments;} else {this.cachedMethodArguments = null;}this.cached = true;}}}if (arguments != null) {try {// 调用目标方法ReflectionUtils.makeAccessible(method);method.invoke(bean, arguments);} catch (InvocationTargetException ex) {throw ex.getTargetException();}}
}

2.3. setter方法Autowire

Spring允许使用setter方法进行依赖注入,这种方式需要在注册BeanDefinition时为其指定AutowireMode参数,有几个可选的值:

  • AUTOWIRE_NO
  • AUTOWIRE_BY_NAME
  • AUTOWIRE_BY_TYPE
  • AUTOWIRE_CONSTRUCTOR
  • AUTOWIRE_AUTODETECT

例如:

GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(UserService.class);
// 指定使用类型进行依赖注入
beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);registry.registerBeanDefinition("userService", beanDefinition);

源码在populateBean流程中,这个方法的代码之前记录过,此处再看一下setter注入的逻辑:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {// ... 略PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);// 此处处理setter方法注入// 1. 从Bean类型解析property和对应的setter方法,将property名称和对应要注入的Bean对象封装到PropertyValues中// 2. 这里有根据属性类型和根据属性名称注入两种模式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;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);// 调用InstantiationAwareBeanPostProcessor的postProcessProperties方法// AutowiredAnnotationBeanPostProcessor处理器可以处理@Autowired和@Value注解,前文详细介绍了PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}}// 默认falseif (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}checkDependencies(beanName, mbd, filteredPds, pvs);}// 使用setter方法为属性注入依赖// 不再展开分析if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);}
}

3. @Bean方法参数Autowire

3.1. 注册BeanDefinition

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {ConfigurationClass configClass = beanMethod.getConfigurationClass();MethodMetadata metadata = beanMethod.getMetadata();String methodName = metadata.getMethodName();AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);// 获取BeanName和别名List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));String beanName = (!names.isEmpty() ? names.remove(0) : methodName);// 注册别名for (String alias : names) {this.registry.registerAlias(beanName, alias);}// 是否覆盖已存在Bean的判断,allowBeanDefinitionOverriding属性用于设置是否允许覆盖// 代码略// 创建BeanDefinitionConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));if (metadata.isStatic()) {// 静态方法if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());} else {beanDef.setBeanClassName(configClass.getMetadata().getClassName());}// @Bean方法名beanDef.setUniqueFactoryMethodName(methodName);} else {// 实例方法// FactoryBeanName = Configuration类的BeanNamebeanDef.setFactoryBeanName(configClass.getBeanName());// @Bean方法名beanDef.setUniqueFactoryMethodName(methodName);}if (metadata instanceof StandardMethodMetadata) {beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());}// 设置AutowireMode = AUTOWIRE_CONSTRUCTORbeanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);Autowire autowire = bean.getEnum("autowire");if (autowire.isAutowire()) {beanDef.setAutowireMode(autowire.value());}boolean autowireCandidate = bean.getBoolean("autowireCandidate");if (!autowireCandidate) {beanDef.setAutowireCandidate(false);}// initMethod及destroyMethod略// Scope及Proxy略this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}

3.2. 创建实例

上文介绍过,创建Bean实例逻辑在AbstractAutowireCapableBeanFactory类的createBeanInstance方法中,其中这段代码用于创建@Bean实例:

// 使用工厂创建Bean实例,@Bean注解标注的方法会使用这种方式创建Bean实例
if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);
}

instantiateUsingFactoryMethod方法:

protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, Object[] explicitArgs) {return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}

instantiateUsingFactoryMethod方法代码较多,此处简单介绍一下流程:

  1. mbd获取factoryBeanNameConfiguration类的BeanName并从容器里面获取这个factoryBean对象;
  2. 获取用来创建BeanMethod候选集;
  3. 如果Method候选集只有一个方法且该方法无参数,直接使用这个方法创建Bean
  4. 如果Method候选集有多个方法,排序,参数多的在前面;
  5. 遍历Method候选集,从容器里面获取方法参数Bean,选择最优的Method
  6. 使用最优Method创建Bean

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/595522.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【占用网络】VoxFormer 基于视觉的3D语义场景方案 CVPR 2023

前言 本文分享“占用网络”方案中&#xff0c;来自CVPR2023的VoxFormer&#xff0c;它基于视觉实现3D语义场景补全。 使用Deformable Attention从图像数据中&#xff0c;预测三维空间中的体素占用情况和类别信息。 VoxFromer是一个两阶段的框架&#xff1a; 第一个阶段&…

理解UML中的依赖关系

理解UML中的依赖关系 在面向对象的设计中&#xff0c;理解各种类之间的关系对于构建一个清晰、可维护的系统至关重要。UML&#xff08;统一建模语言&#xff09;为我们提供了一种可视化这些关系的方式。今天&#xff0c;我们将深入探讨UML中的依赖关系&#xff08;Dependency&a…

苹果Vision Pro将于1月27日上市!

在无数期待中&#xff0c;苹果全新产品Vision Pro头显终于定下上市日期。 彭博社记者马克古曼&#xff08;Mark Gurman&#xff09;于近日在X&#xff08;前推特&#xff09;平台爆料了这一信息&#xff0c;预计苹果Vision Pro头显将于2024年1月27日率先在美国上市。 在过去看…

力扣92. 反转链表 II

链表 思路&#xff1a; 使用一个 dummy 指针迭代到 left&#xff1b;然后反转 (right - left) 个 node&#xff1b;之后将剩余的 node 继续串起来即可&#xff1b; class Solution { public:ListNode *reverseBetween(ListNode *head, int left, int right) {// 设置 dummyNo…

【QT】QString类型中,Empty和NULL有什么区别在qt里,对比C#

在 Qt 中&#xff0c;QString 类型的字符串使用 isEmpty() 方法来检查字符串是否为空&#xff0c;而不是使用 null。这与 C# 中的 string.IsNullOrEmpty 方法略有不同。 QString::isEmpty()&#xff1a; 用于检查字符串是否为空。一个 QString 对象可能是空字符串&#xff0c;即…

如何计算非线性负载的功率需求?

非线性负载的功率需求计算是一个相对复杂的过程&#xff0c;因为非线性负载的电流和电压之间的关系不是简单的正比关系。在计算非线性负载的功率需求时&#xff0c;需要考虑负载的特性、工作状态以及电源电压等因素。 确定负载的类型&#xff1a;首先需要了解负载的具体类型&am…

客户端、服务端在一个c++程序里

一个项目&#xff0c;同时包含客户端、服务端的设计模式称为双工/双端模式。 这种设计模式下&#xff0c;程序具有同时作为客户端和服务端的功能&#xff0c;可以与其他程序通信&#xff0c;并作为服务端接收其他程序的请求。 若开发双工模式的系统&#xff0c;需具备以下内容…

【C语言】浙大版C语言程序设计(第三版) 练习7-4 找出不是两个数组共有的元素

前言 最近在学习浙大版的《C语言程序设计》&#xff08;第三版&#xff09;教材&#xff0c;同步在PTA平台上做对应的练习题。这道练习题花了比较长的时间&#xff0c;于是就写篇博文记录一下我的算法和代码。 2024.01.03 题目 练习7-4 找出不是两个数组共有的元素 作者 张彤…

BIO、NIO

网络通信基本常识 什么是socket? socket 是应用层与 TCP/P 协议族通信的中间软件抽象层&#xff0c;它是一组接口&#xff0c;主机A 的应用程序要能和主机B 的应用程序通信&#xff0c;必须通过 Socket 建立连接。 短连接 SOCKET 连接发送完数据后马上断开连接 长连接 建…

RocketMQ单机部署完整学习笔记

文章目录 前言一、RocketMQ是什么&#xff1f;二、使用步骤1.安装MQ1.安装JDK2.安装mq3.MQ配置(核心) 2.搭建可视化dashboard1.下载源码2.修改配置3.启动 3.整合java1.生产者2.消费者3.启动生产者4.启动消费者5.dashboard添加消费组 三、总结全部的配置 前言 本文是基于4.X版本…

静态网页设计——电影角(HTML+CSS+JavaScript)

前言 声明&#xff1a;该文章只是做技术分享&#xff0c;若侵权请联系我删除。&#xff01;&#xff01; 使用技术&#xff1a;HTMLCSSJS 主要内容&#xff1a;本网页主要利用HTML语言编写&#xff0c;简要介绍世界上一些主要国家&#xff0c;例如&#xff0c;中&#xff0c;…

K8S三种发布方式和声明式资源管理

蓝绿发布 把应用服务集群标记位两个组&#xff0c;蓝组和绿组&#xff0c;先升级蓝组&#xff0c;先要把蓝组从负载均衡当中移除&#xff0c;绿组继续提供服务&#xff0c;蓝组升级完毕&#xff0c;再把绿组从负载均衡当中移除&#xff0c;绿组升级&#xff0c;然后都加入回负载…

【已解决】You have an error in your SQL syntax

报错讯息 java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘desc,target_url,sort,status,create_by,modify_by,created,last_update_time FROM…

跑通CLAM

项目场景&#xff1a; 从github上下载CLAM代码&#xff0c;上传Camelyon-16中的部分WSI图像&#xff0c;将代码跑通。 CLAM项目地址&#xff1a; GitHub - mahmoodlab/CLAM: Data-efficient and weakly supervised computational pathology on whole slide images - Nature …

Linux中经常使用的相关命令

查看硬盘存储容量使用情况&#xff1a; df -lh 列出 /bin 目录中的 5 个最大文件: ls -lSh /bin | head -5 删除文件和文件夹 在Linux中&#xff0c;要删除文件的命令是rm。你可以使用以下命令来删除一个文件&#xff1a; rm file_name如果要删除多个文件&#xff0c;可…

如何读取excel任意单元格内容的代码(vba,py)

如何读取excel任意单元格内容的代码 ━━━━━━━━━━━━━━━━━━━━━━ 你可以使用 VBScript&#xff08;VBS&#xff09;来读取 Excel 文件中的任意单元格内容。以下是一个简单的 VBScript 代码示例&#xff0c;使用 CreateObject 来操作 Excel 应用程序&#xff…

Tomcat系统架构与原理剖析及手写Tomcat及源码导入学习

文章目录 1 Tomcat官网2 Tomcat **系统架构与原理剖析**2.1 浏览器访问服务器的流程2.2 **Tomcat** **系统总体架构****2.2.1 Tomcat** **请求处理⼤致过程**2.2.2 **Tomcat Servlet**容器处理流程2.2.3 **Tomcat** 系统总体架构2.3 **Tomcat** **连接器组件** Coyote2.4 **Tom…

高级RAG(四):RAGAs评估

之前我完成了父文档检索器和llamaIndex从小到大的检索这两篇博客&#xff0c;我在这两篇博客中分别介绍了使用langchain和llamaIndex进行文档检索的方法和步骤&#xff0c;其中包含了不同的RAG的检索策略&#xff0c;通常来说一个典型的RAG系统一般包含两个主要的部件&#xff…

程序媛的mac修炼手册--MacOS系统更新升级史

啊&#xff0c;我这个口罩三年从未感染过新冠的天选免疫王&#xff0c;却被支原体击倒&#x1f637;大意了&#xff0c;前几天去医院体检&#xff0c;刚检查完出医院就摘口罩了&#x1f926;大伙儿还是要注意戴口罩&#xff0c;保重身体啊&#xff01;身体欠恙&#xff0c;就闲…

‘react-native‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

原因&#xff1a;没有下载react-native 解决下载react-native npm i -g react-native-cli