org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
属性注入注解方式和xml配置方式,使用不同的逻辑。
注解通过从beanFactory中找实例,反射注入;xml则是通过PropertyValues,反射调用set方法注入。

 protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {。。。。。// bean处理器的方法,实例化后处理方法if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}}}// 这里得到的是xml配置中设置的属性-值PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);int resolvedAutowireMode = mbd.getResolvedAutowireMode();// 如果设置为自动注入。// AUTOWIRE_BY_NAME会根据属性的名称,从beanFactory中找bean,添加到newPvs属性集合中// AUTOWIRE_BY_TYPE根据属性的类型找bean,添加到属性集合中// 当然如果已经在xml中设置值的就不会在找了// xml是手动设置,这里是自动配置,直接根据属性的名称或者类型找bean.if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);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);PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}// 这里是注解注入的处理逻辑,使用bean处理器的方法。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;}}}if (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}checkDependencies(beanName, mbd, filteredPds, pvs);}// 这里设值是属性集合中的属性键值对。if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);}}

xml配置的bean,会将属性和值封装在PropertyValue中,添加到属性集合中,通过反射调用set方法注入。逻辑在applyPropertyValues方法中;

注解的注入则是使用bean处理器,通过反射直接对属性赋值

直接分析注解的方式,先来看看注解的使用:

@Autowired注解:可以标注在属性上,方法上。

  1. 标注在属性上,会根据属性的类型找bean。
  2. 标注在方法上,会根据方法参数的类型找bean.
  3. 如果有多个类型一致的;会跑异常,解决方式设置@primary bean,设置一个候选的。或者在类型一致的里面根据名称选出一个bean,使用@Qualifier注解;

@Resource注解:可以标注在属性上,方法上,但是这个方法的参数个数必须是1个。

  1. 标注在属性上,默认是@Resource的value值作为找bean的名称;如果没有,使用属性的名称;如果不存在该名称的bean,会根据bean的类型找;
  2. 如果标注在方法上,如果这个方法的名称不是JavaBean规范,那么会根据方法名成找bean,没有找到会根据方法参数的类型找。如果是javaBean规范,那么找bean的名称就是属性名称,根据名称找,根据bean名称没有找到,会根据参数类型找。

CommonAnnotationBeanPostProcessor

使用@Resource注入,需要明确是@Resource不是Spring的注解,是JSR标准

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties直接看这个注入的方法了,其实在依赖输入之前,postProcessMergedBeanDefinition这个方法会进行依赖注入的解析,保存缓存中,在postProcessProperties是从缓存找取,执行注入逻辑。所以直接看postProcessProperties方法也无妨。

 public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {// 缓存了需要输入数据的信息InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);try {// 注入逻辑。metadata.inject(bean, beanName, pvs);}catch (Throwable ex) {throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);}return pvs;}

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#buildResourceMetadata
解析需要注入的信息

 private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {return InjectionMetadata.EMPTY;}List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();Class<?> targetClass = clazz;do {final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();// 得到所有的属性信息ReflectionUtils.doWithLocalFields(targetClass, field -> {// 兼容其他注解。。。。。。// 我们只关注Resource注解的。else if (field.isAnnotationPresent(Resource.class)) {// 静态的属性不能注入if (Modifier.isStatic(field.getModifiers())) {throw new IllegalStateException("@Resource annotation is not supported on static fields");}// 将属性封装为ResourceElementif (!this.ignoredResourceTypes.contains(field.getType().getName())) {currElements.add(new ResourceElement(field, field, null));}}});ReflectionUtils.doWithLocalMethods(targetClass, method -> {Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {return;}if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {                // 兼容其他注解。。。。。// 只看Resource注解else if (bridgedMethod.isAnnotationPresent(Resource.class)) {// 静态的方法不能注入if (Modifier.isStatic(method.getModifiers())) {throw new IllegalStateException("@Resource annotation is not supported on static methods");}// 方法参数个数不是1的会抛异常。Class<?>[] paramTypes = method.getParameterTypes();if (paramTypes.length != 1) {throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);}// 封装为ResourceElementif (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);currElements.add(new ResourceElement(method, bridgedMethod, pd));}}}});elements.addAll(0, currElements);targetClass = targetClass.getSuperclass();}// 循环,从父类中是否有标注注解的。while (targetClass != null && targetClass != Object.class);return InjectionMetadata.forElements(elements, clazz);}

解析注解:

  1. 静态属性和静态方法不能出入;
  2. 方法的参数个数必须是1个,否则会跑异常。
  3. 将数据给封装在ResourceElement再添加到集合中。

注入逻辑:

 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()) {// 遍历InjectedElement集合,调用InjectedElement 的注入方法。for (InjectedElement element : elementsToIterate) {if (logger.isTraceEnabled()) {logger.trace("Processing injected element of bean '" + beanName + "': " + element);}element.inject(target, beanName, pvs);}}}
     protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)throws Throwable {// 属性,通过反射if (this.isField) {Field field = (Field) this.member;ReflectionUtils.makeAccessible(field);field.set(target, getResourceToInject(target, requestingBeanName));}else {if (checkPropertySkipping(pvs)) {return;}try {// 方法,方法的反射。Method method = (Method) this.member;ReflectionUtils.makeAccessible(method);method.invoke(target, getResourceToInject(target, requestingBeanName));}catch (InvocationTargetException ex) {throw ex.getTargetException();}}}

getResourceToInject通过该方法得到值;
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject

     protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {//这里有一个懒加载的操作。// 如果使用@lazy注解标注了,会给创建一个代理,只有再使用的时候才会取bean工厂中找bean//非懒加载的会立刻执行找bean的逻辑,返回结果。懒加载是先返回要给代理,等调用放的时候再去执行找bean的过程。return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :getResource(this, requestingBeanName));}
 protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)throws NoSuchBeanDefinitionException {Object resource;Set<String> autowiredBeanNames;// 如果是属性,这里是注解value的值,没有指定,就是属性的名称// 如果是方法,javabean标准,是属性名称;不是javaBean标准,则是方法名称。String name = element.name;if (factory instanceof AutowireCapableBeanFactory) {AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;DependencyDescriptor descriptor = element.getDependencyDescriptor();// 如果按照名称找,但是名称没有,就按类型找。if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {autowiredBeanNames = new LinkedHashSet<>();resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);if (resource == null) {throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");}}// 按照名称找。else {resource = beanFactory.resolveBeanByName(name, descriptor);autowiredBeanNames = Collections.singleton(name);}}else {resource = factory.getBean(name, element.lookupType);autowiredBeanNames = Collections.singleton(name);}if (factory instanceof ConfigurableBeanFactory) {ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;for (String autowiredBeanName : autowiredBeanNames) {if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);}}}return resource;}

按照名称找不到,就会按照类型找。

     public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {super(member, pd);Resource resource = ae.getAnnotation(Resource.class);// Resource 指定的bean名称String resourceName = resource.name();Class<?> resourceType = resource.type();this.isDefaultName = !StringUtils.hasLength(resourceName);// 如果使用默认的名称if (this.isDefaultName) {// 属性名称或者方法名称resourceName = this.member.getName();// 如果是方法,兵器是set开头,长度>3,是javaBean规范// 内省机制找到属性名。否则还是方法名称。if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {resourceName = Introspector.decapitalize(resourceName.substring(3));}}else if (embeddedValueResolver != null) {resourceName = embeddedValueResolver.resolveStringValue(resourceName);}if (Object.class != resourceType) {checkResourceType(resourceType);}else {// No resource type specified... check field/method.resourceType = getResourceType();}this.name = (resourceName != null ? resourceName : "");this.lookupType = resourceType;String lookupValue = resource.lookup();this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());Lazy lazy = ae.getAnnotation(Lazy.class);this.lazyLookup = (lazy != null && lazy.value());}

AutowiredAnnotationBeanPostProcessor

使用@Autowired注解注入。该注解是Spring的注解。

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#buildResourceMetadata

 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,@Inject// @Inject是JSR标注的注解。MergedAnnotation<?> ann = findAutowiredAnnotation(field);if (ann != null) {// 静态的不行if (Modifier.isStatic(field.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static fields: " + field);}return;}// 封装为AutowiredFieldElementboolean required = determineRequiredStatus(ann);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())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static methods: " + method);}return;}if (method.getParameterCount() == 0) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation should only be used on methods with parameters: " +method);}}// 封装为AutowiredMethodElementboolean 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);}
  1. 静态的都不行
  2. 属性封装为AutowiredFieldElement;方法封装为AutowiredMethodElement

属性:

     protected void inject(Object bean, @Nullable String beanName, @Nullable 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);Assert.state(beanFactory != null, "No BeanFactory available");TypeConverter typeConverter = beanFactory.getTypeConverter();try {//根据类型找value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);}catch (BeansException ex) {throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);}synchronized (this) {// 放入缓存if (!this.cached) {if (value != null || this.required) {this.cachedFieldValue = desc;registerDependentBeans(beanName, autowiredBeanNames);if (autowiredBeanNames.size() == 1) {String autowiredBeanName = autowiredBeanNames.iterator().next();if (beanFactory.containsBean(autowiredBeanName) &&beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());}}}else {this.cachedFieldValue = null;}this.cached = true;}}}// 反射给属性赋值if (value != null) {ReflectionUtils.makeAccessible(field);field.set(bean, value);}}}

方法:

     protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {if (checkPropertySkipping(pvs)) {return;}Method method = (Method) this.member;Object[] arguments;if (this.cached) {// Shortcut for avoiding synchronization...arguments = resolveCachedArguments(beanName);}else {int argumentCount = method.getParameterCount();arguments = new Object[argumentCount];DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);Assert.state(beanFactory != null, "No BeanFactory available");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;}//找到的bean放再数组中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();}}}

有个问题;静态的属性和方法都还不能用注解,那如果就是想用静态的怎么版呢?

解决静态属性,静态方法注入的问题

可以这样

@Component
public class UserHelper {static UCClient ucClient;@Autowiredpublic void setUcClient(UCClient ucClient) {UserHelper.ucClient = ucClient;}
}

但是想想工具类都是静态的,不用交给spring管理。
SmartInitializingSingleton该接口会在所有的bean都实例化之后调用

@Component
public class AutowireStaticSmartInitializingSingleton implements SmartInitializingSingleton {@Autowiredprivate AutowireCapableBeanFactory beanFactory;/*** 当所有的单例Bena初始化完成后,对static静态成员进行赋值*/@Overridepublic void afterSingletonsInstantiated() {// 交给工厂,给我注如,beanFactory.autowireBean(new UserHelper());}
}

这样该类就不用加@Component注解。工具类交给beanFactory,让工厂注入。

public class UserHelper {static UCClient ucClient;@Autowiredpublic void setUcClient(UCClient ucClient) {UserHelper.ucClient = ucClient;}
}

或者这样:

@Component
public class AutowireStaticSmartInitializingSingleton implements SmartInitializingSingleton {@Autowiredprivate AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor;// 就是让处理器给注入@Overridepublic void afterSingletonsInstantiated() {autowiredAnnotationBeanPostProcessor.processInjection(new UserHelper());}
}

还有一个问题,就是工厂找bean,是如何找的呢?就是方法beanFactory.resolveDependency的逻辑是什么样呢?

beanFactory.resolveDependency方法

 public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Set<String> autowiredBeanNames, @Nullable 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注解的value值// @value(#{beanName}) 注入的是bean// @value(${property-key}) 属性赋值// 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) {// 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()));}}// 如果类型是集合类型的,数组,集合,Map,进入到此Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);if (multipleBeans != null) {return multipleBeans;}// 不是集合类型的,就直接找对应的类型。Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);if (matchingBeans.isEmpty()) {// 如果没有找到,还是必须的,那么就抛异常if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}return null;}String autowiredBeanName;Object instanceCandidate;// 如果找到了,有多个候选的if (matchingBeans.size() > 1) {// 筛选// 1. 设置primary// 2. Priority注解// 3.bean的名称和属性的名称匹配。// 如果还欸有筛选出来就抛异常autowiredBeanName = 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) {instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);}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);}}
  1. 处理@value注解
  2. 类型是集合类型的
  3. 普通类类型的。
  4. 如果没有找到,又是必须的,报错
  5. 如果找到了多个,就筛选1,设置primary的,2.注解Priority的,3.bean名和属性名一致的;如果还灭有筛选出来就报错。

findAutowireCandidates方法

找出对应类型的所有bean

 protected Map<String, Object> findAutowireCandidates(@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {//遍历所有的beanName,从里面找出beanDefinition,找出class,对比clas类型和requiredTypeString[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);// 处理spring内部的实例// applicationcontext ,beanFactory等。。for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {Class<?> autowiringType = classObjectEntry.getKey();if (autowiringType.isAssignableFrom(requiredType)) {Object autowiringValue = classObjectEntry.getValue();autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);if (requiredType.isInstance(autowiringValue)) {result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);break;}}}// 得到所有类型一样的// 进行泛型和@Qualifier的筛选for (String candidate : candidateNames) {if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}// 如果没有则放宽条件:可以自引用;泛型不在精确匹配if (result.isEmpty()) {boolean multiple = indicatesMultipleBeans(requiredType);// Consider fallback matches if the first pass failed to find anything...DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();// 泛型不在精确匹配for (String candidate : candidateNames) {if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {addCandidateEntry(result, candidate, descriptor, requiredType);}}    // 可以自引用if (result.isEmpty() && !multiple) {// Consider self references as a final pass...// but in the case of a dependency collection, not the very same bean itself.for (String candidate : candidateNames) {if (isSelfReference(beanName, candidate) &&(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&isAutowireCandidate(candidate, fallbackDescriptor)) {addCandidateEntry(result, candidate, descriptor, requiredType);}}}}return result;}
  1. 找到所有的类型一样的
  2. 泛型筛选
  3. @Qualifier筛选名称。

泛型是精确匹配:
注入的是RedisTemplate<Object, Object>;但是容器中只有RedisTemplate<String, String>由于精确匹配,不能注入

【Spring-IOC】依赖注入相关推荐

  1. java调用外联服务用xml,Spring IOC 依赖注入的两种方式:XML和注解

    IoC,直观地讲,就是容器控制程序之间的关系,而非传统实现中,由程序代码直接操控.这也就是所谓"控制反转"的概念所在.控制权由应用代码中转到了外部容器,控制权的转移是所谓反转.Io ...

  2. Spring IoC依赖注入-6

    1. 依赖注入的模式和模型: Spring 提供了哪些依赖注入的模式和类型? 手动模式 - 配置或者编程的方式,提前安排注入规则 XML资源配置元信息 Java 注解配置元信息 API 配置元信息 自 ...

  3. java框架篇---spring IOC依赖注入

    spring依赖注入的方式有4种 构造方法注入 属性注入 工厂注入 注解注入 下面通过一个实例统一讲解: User.java package com.bjsxt.model;public class ...

  4. 小白入门spring——IOC依赖注入

    (1)什么是依赖注入 Dl(dependency injection)依赖注入 含义:就是给对象的属性设置值. 原来给对象的属性设置值: set方法给对象设置值和构造方法给对象初始化的时候设置值. ( ...

  5. java中四种注入注解,Spring中依赖注入的四种方式

    在Spring容器中为一个bean配置依赖注入有三种方式: · 使用属性的setter方法注入  这是最常用的方式: · 使用构造器注入: · 使用Filed注入(用于注解方式). 使用属性的sett ...

  6. Spring字段依赖注入示例

    学习如何编写Spring Field Injection示例 . 字段注入是Spring框架 依赖注入的一种 . 在本教程中,我们将编写几个类,并看一看现场注入工程. 有关Spring依赖注入的更多信 ...

  7. 据说,80%的人没有真正理解了Spring的依赖注入

    前言 提起Spring,大家肯定不陌生,它是每一个Java开发者绕不过去的坎.Spring 框架为基于 java 的企业应用程序提供了一整套解决方案,方便开发人员在框架基础快速进行业务开发. 在官网中 ...

  8. Spring框架----Spring的依赖注入

    1.spring的依赖注入的概念 依赖注入:dependency Injection IOC的作用:降低程序之间的依赖关系,但不是消除. 依赖关系的管理:以后都交给了spring来维护 在当前类中需要 ...

  9. spring(一)依赖注入与 SPEL

    Spring之依赖注入与 SPEL 一.控制反转与依赖注入 二.helloworld 三.构造注入 四.级联注入 五.单例与多例 六.工厂方法创建 Bean 七.包扫描管理 bean 八.SPEL与资 ...

  10. 【Spring】依赖注入的几种方式

    在上篇文章中我着重介绍了Spring的控制反转和依赖注入的概念,那么依赖注入有那几种方式呢?他们的优缺点分别是什么,我将在本章中详细讲解. Spring的依赖注入根据对象类型注入可以分为属性注入和对象 ...

最新文章

  1. [YTU]_2922(Shape系列-8)
  2. GNOME 3.31.91 发布,3.32 发布周期第二个 beta 版
  3. uniapp的目录结构反思与整理 app.vue【base】pages.json【配置】main.json【框架入口文件】
  4. 不确定规划及应用代码_性能测试划分之应用领域
  5. PaperNotes(2)-Generative Adversarial Nets
  6. C++primer第九章 顺序容器 9.5 额外的string操作
  7. iframe的2个问题
  8. 北通usb手柄_多平台适配,北通斯巴达2无线版手柄操控灵敏
  9. cheerio获取元素内文本,但不包括其子元素内的文本值的方法
  10. 多所985、211高校教授被通报!国自然发布处理决定!
  11. 社交网络电影深度解析论文,社交网络 电影解析
  12. 无限循环小数四则运算_无限循环小数能做加减乘除四则运算吗?无限不循环小数能做吗??...
  13. 数据加速器 GooseFS 1.3.0 版本正式发布
  14. XXE漏洞介绍及利用
  15. 关于弹性布局flex
  16. 智慧建造安全质量管理数字化解决方案
  17. matlab调用zlg,stm32读取ZLG7290按键键值实验源码
  18. 图解通信原理与案例分析-35:以太网MAC层的通信原理--MAC帧格式与调度策略:载波侦听与冲突检测CSMA/CD、载波侦听与冲突避免(信道空闲保证)CSMA/CA、流控
  19. word文档中enter到下一页
  20. 淘宝直通车选词怎么做?大神导航,一个神奇的网站,从此开启大神之路!

热门文章

  1. SLAM--单目尺度漂移(相似变换群Sim3)
  2. 从Xcode中的动态库中剥离不需要的架构 Submit to App Store issues: Unsupported Architecture X86_64, i386
  3. linux 安装socket扩展,51CTO博客-专业IT技术博客创作平台-技术成就梦想
  4. linux拷贝数据库文件夹,手工拷贝数据库文件建立新的数据库实例过程
  5. matlab光流彩图,hs 用matlab编译的经典光流算法HS ,附有程序需 图像 238万源代码下载- www.pudn.com...
  6. deepin mysql管理工具_[LINUX]DeepIn下基础开发环境搭建
  7. 类型转换操作符(C++)
  8. DataType error: cannot resolve DataType of [[[D
  9. python爬虫总结
  10. Android事件处理