Spring的依赖注入

Spring原生依赖注入(已过时,不推荐使用)

AbstractAutowireCapableBeanFactory类内的 populateBean方法(属性注入)

resolvedAutowireMode就是

 autowire值的编号

		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			// MutablePropertyValues是PropertyValues具体的实现类
			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;
		}

ByType

ByName

AbstractAutowireCapableBeanFactory类的 autowireByName方法

	protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		// 当前Bean中能进行自动注入的属性名
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		// 遍历每个属性名,并去获取Bean对象,并设置到pvs中
		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);
				// 记录一下propertyName对应的Bean被beanName给依赖了
				registerDependentBean(propertyName, beanName);
				if (logger.isTraceEnabled()) {
					logger.trace("Added autowiring by name from bean name '" + beanName +
							"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
							"' by name: no matching bean found");
				}
			}
		}
	}

获得注入的属性名字

属性描述器,这个pds里面存储的

就是 去分析 get和set方法 两个有其一就行 但是必须规范 set必须有形参,get必须有返回值,

getXXX/setXXX这个XXX就会被当作一个pd的name属性 pd里面会有readMethod或者writeMethod(根据实际分析而得的);

	protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
//		BeanWrapper里面有实例对象
		Set<String> result = new TreeSet<>();
		PropertyValues pvs = mbd.getPropertyValues();
//		属性描述器(规范)
		PropertyDescriptor[] pds = bw.getPropertyDescriptors();

		// 什么样的属性能进行自动注入?
		// 1.该属性有对应的set方法
		// 2.没有在ignoredDependencyTypes中
		// 3.如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
		// 4.属性类型不是简单类型,比如int、Integer、int[]
		for (PropertyDescriptor pd : pds) {
			if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
					!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
				result.add(pd.getName());
			}
		}
		return StringUtils.toStringArray(result);
	}

String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);这个结果,就是bds通过遍历,并且过滤(必须有一个set方法)得到的一个集合

过滤条件: 必须有set方法,这个属性不是简单类型(String int ......)

                   之前操作BD时没有手动指定属性值

	// 遍历每个属性名,并去获取Bean对象,并设置到pvs中
		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);

             containsBean(propertyName)

需要 这个属性 有BD在BD集合中,并且是单例的   ,最后放到pvs中

                                                                                                                                                          

Spring的扩展依赖注入(@Autowired 或者 @Resource...推荐)

@Autowired @Value @Inject

找到对应的切点

applyMergedBeanDefinitionPostProcessors中

会遍历循环  MergedBeanDefinitionPostProcessor

会找到一个 AutowiredAnnotationBeanPostProcessor 的一个后置处理器

 

 这个方法这里执行后,会将找到的切点放到injectionMetadataCache这个缓存中,下次调用这个就可以直接拿到 类的对应切点

	private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable 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所有注入点存放发地方
		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);
					}
					// 解析注入点并缓存  就是哪一个字段 / 方法上加了 @AutoWare 就是一个注入点
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

buildAutowiringMetadata方法

	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		// 如果一个Bean的类型是String...,那么则根本不需要进行依赖注入
		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<>();

			// 遍历targetClass中的所有Field
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				// field上是否存在@Autowired、@Value、@Inject中的其中一个
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
					// static filed不是注入点,不会进行自动注入
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}

					// 构造注入点
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			// 遍历targetClass中的所有Method
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {

				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				// method上是否存在@Autowired、@Value、@Inject中的其中一个
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					// static method不是注入点,不会进行自动注入
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					// set方法最好有入参
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					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);
	}

大概流程:

        首先会判断这个类是不是需要进行Autowired切点的类

        主要就是判断这个类是不是 java包下的,不是才会继续找切点

         循环找切点(先找子类,再找父类,直到object)       

                找 字段切点

                        遍历所有字段

                        找哪些字段上标有@Autowired @Value @Inject

                        判断这个字段是不是静态的,如果是,直接忽略这个字段

                                {原因:假设这个场景:A类是原型的 B类也是原型的

                                        A 类中 有B类的成员遍历 加了@Autowired  还是静态的

                                        那当我调用了两次getBean(A),就会得到两个 A对象,但是当我们获  得第二个对象时,就会把第一个对象的B成员属性给更改了,所以Spring认为这个是不符合规范的,所以 就忽略了静态字段

                                }

                        会获取 @Autowired 的required的值(是否必须要依赖注入,如果是false,就算没找到要注入的值,直接给一个null,如果是ture 没有找到,就会报错)

                        如果符合以上要求 ,就将这个 切入点以及required(封装为AutowiredFieldElement)记录下来

                        一个类的 切点字段 会放到currElements

                       

                        {有个细节,因为在一个循环里,如果这个类有父类,在遍历父类之后,会将父类的currElements放到elements(类及其父类的currElements集合)的最前面,也是符合逻辑的,要注入属性,父类优先}

                找 方法切点

                        会有一个(桥接方法),大概意思就是,方法参数出现了泛型,字节码层面会有两个方法,一个是方法参数是Object 另一个就是真正要注入的,会根据一系列判断,找到那个真正要注入的(可以忽略,因为我也不知道是不是正确的,但是有这个逻辑)

                        遍历一个类的所有method上是否存在@Autowired、@Value、@Inject中的其中一个

                        排除static(理由和字段的差不多)

                        这个方法最好有 至少有一个形参 (要不然 注入个 der)(没有就会打印一个日志,但并不会排除),

                        获取required的值

                          如果符合以上要求 ,就将这个 切入点以及required(封装为AutowiredMethodElement)记录下来

                        一个类的 切点方法 也 会放到currElements

统一封装到InjectionMetadata这个类里面

开始属性注入

会找到AutowiredAnnotationBeanPostProcessor 的postProcessProperties方法

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		// 找注入点(所有被@Autowired注解了的Field或Method)
		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;
	}

 findAutowiringMetadata这个方法以经在上面执行过了,这次直接从缓存中拿就行,不需要再次遍历字段和方法了

拿到注入点后,就要开始对注入点进行属性注入了

 会遍历所有的注入点(AutowiredMethodElement,AutowiredFieldElement)会调用这两个对应 的inject方法

AutowiredFieldElement

		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {

			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				// 对于原型Bean,第一次创建的时候,也找注入点,然后进行注入,此时cached为false,注入完了之后cached为true
				// 第二次创建的时候,先找注入点(此时会拿到缓存好的注入点),也就是AutowiredFieldElement对象,此时cache为true,也就进到此处了
				// 注入点内并没有缓存被注入的具体Bean对象,而是beanName,这样就能保证注入到不同的原型Bean对象
				try {
					value = resolvedCachedArgument(beanName, this.cachedFieldValue);
				}
				catch (NoSuchBeanDefinitionException ex) {
					// Unexpected removal of target bean for cached argument -> re-resolve
					value = resolveFieldValue(field, bean, beanName);
				}
			}
			else {
				// 根据filed从BeanFactory中查到的匹配的Bean对象
				value = resolveFieldValue(field, bean, beanName);
			}

			// 反射给filed赋值
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}

 第一次获取没有缓存:

  会直接调用这个方法 获得这个要注入的值

// 根据filed从BeanFactory中查到的匹配的Bean对象
value = resolveFieldValue(field, bean, beanName);

 通过反射直接写到对象中

// 反射给filed赋值
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}

AutowiredMethodElement

		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			// 如果pvs中已经有当前注入点的值了,则跳过注入
			if (checkPropertySkipping(pvs)) {
				return;
			}
			Method method = (Method) this.member;
			Object[] arguments;
			if (this.cached) {
				try {
					arguments = resolveCachedArguments(beanName);
				}
				catch (NoSuchBeanDefinitionException ex) {
					// Unexpected removal of target bean for cached argument -> re-resolve
					arguments = resolveMethodArguments(method, bean, beanName);
				}
			}
			else {
				arguments = resolveMethodArguments(method, bean, beanName);
			}
			if (arguments != null) {
				try {
					ReflectionUtils.makeAccessible(method);
					method.invoke(bean, arguments);

				}
				catch (InvocationTargetException ex) {
					throw ex.getTargetException();
				}
			}
		}

 和字段的差不多,只是 把单个字段 换成了 ,方法参数值的数组,最后,

通过反射 ,调用这个方法

怎么从ioc找

resolveFieldValue(字段)
	private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {

			//字段  / 方法参数  的名字 和 类型
			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();
			Object value;
			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) {
					Object cachedFieldValue = null;
					if (value != null || this.required) {
						cachedFieldValue = desc;
						// 注册一下beanName依赖了autowiredBeanNames,
						registerDependentBeans(beanName, autowiredBeanNames);
						if (autowiredBeanNames.size() == 1) {
							String autowiredBeanName = autowiredBeanNames.iterator().next();
							if (beanFactory.containsBean(autowiredBeanName) &&
									beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
								// 构造一个ShortcutDependencyDescriptor作为缓存,保存了当前filed所匹配的autowiredBeanName,而不是对应的bean对象(考虑原型bean)
								cachedFieldValue = new ShortcutDependencyDescriptor(
										desc, autowiredBeanName, field.getType());
							}
						}
					}
					this.cachedFieldValue = cachedFieldValue;
					this.cached = true;
				}
			}
			return value;
		}
	}

DependencyDescriptor 是 依赖(字段)的描述器,里面有 ,字段name  和 字段type,

还有bean的class

DependencyDescriptor在找方法参数那里是一个数组

重要的语句

value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

这个resolveDependency中一般都是执行这段代码
	// 在属性或set方法上使用了@Lazy注解,那么则构造一个代理对象并返回,真正使用该代理对象时才进行类型筛选Bean
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);

			if (result == null) {
				// descriptor表示某个属性或某个set方法
				// requestingBeanName表示正在进行依赖注入的Bean
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
解析@Lazy注解

如果字段或者方法参数上标有@Lazy注解,就会在这里根据类型构建一个代理对象,当我们真正去调用这个字段的方法,才会去容器里找对应的bean,然后调用bean的方法,(懒o_o)

没有标

result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);

	@Nullable
	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			// 如果当前descriptor之前做过依赖注入了,则可以直接取shortcut了,相当于缓存
			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);
					// 解析Spring表达式(#{})
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				// 将value转化为descriptor所对应的类型
				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()));
				}
			}

			// 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的所有bean方法,不用进一步做筛选了
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

			// 找到所有Bean,key是beanName, value有可能是bean对象,有可能是beanClass
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				// required为true,抛异常
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {
				// 根据类型找到了多个Bean,进一步筛选出某一个, @Primary-->优先级最高--->name
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					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();
			}

			// 记录匹配过的beanName
			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			// 有可能筛选出来的是某个bean的类型,此处就进行实例化,调用getBean
			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);
		}
	}
 解析@Value
			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);
					// 解析Spring表达式(#{})
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				// 将value转化为descriptor所对应的类型
				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()));
				}
			}

 先获得字段/方法参数 的 类型值

读取@Value(“值”)的 值

字符串的解读:

${}代表 去找环境变量(java -d 后面的 ; 计算机配的环境变量 ;自己手动配的)

 

#{}  这样的代表spring表达式

这个非常不常用 

举个例子#{orderService} 就是去容器里找一个叫orderService的对象赋给字段/方法参数

“2313123”直接就是字符串 或者上面是¥{1231} ,#{12313}原因就是环境变量里没找到,或者容器里没找到 ,就认为可能就是要赋值这个字符串

这里的逻辑,就是 通过类型转换器 来实现的,看看有没有能转成功的

没有就会抛异常

没有标@Value 
类型判断(是不是返回多个值) 只举一个Map 其他原理差不多,关键,我们也不会这么用0_0

如果是集合/Map/数组

	// 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的所有bean方法,不用进一步做筛选了
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

Map

        判断map的key是不是String 不是直接返回null (指的是multipleBeans 是null,不是找的方法(doResolveDependency)结束了)

        findAutowireCandidates找到所有符合类型的bean,key是beanname,value就是bean对象,

能找到就返回,没找到就返回null,继续下面的逻辑

else if (Map.class == type) {
			ResolvableType mapType = descriptor.getResolvableType().asMap();
			Class<?> keyType = mapType.resolveGeneric(0);
			// 如果Map的key不是String
			if (String.class != keyType) {
				return null;
			}
			Class<?> valueType = mapType.resolveGeneric(1);
			if (valueType == null) {
				return null;
			}
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
					new MultiElementDescriptor(descriptor));
			if (matchingBeans.isEmpty()) {
				return null;
			}
			if (autowiredBeanNames != null) {
				autowiredBeanNames.addAll(matchingBeans.keySet());
			}
			return matchingBeans;
		}
 根据类型判断只要一个的
	// 找到所有Bean,key是beanName, value有可能是bean对象,有可能是beanClass
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				// required为true,抛异常
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

			if (matchingBeans.size() > 1) {
				// 根据类型找到了多个Bean,进一步筛选出某一个, @Primary-->优先级最高--->name
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					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();
			}

protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
		Class<?> requiredType = descriptor.getDependencyType();
		// candidates表示根据类型所找到的多个Bean,判断这些Bean中是否有一个是@Primary的
		String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
		if (primaryCandidate != null) {
			return primaryCandidate;
		}

		// 取优先级最高的Bean
		String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
		if (priorityCandidate != null) {
			return priorityCandidate;
		}

		// Fallback
		// 匹配descriptor的名字,要么是字段的名字,要么是set方法入参的名字
		for (Map.Entry<String, Object> entry : candidates.entrySet()) {
			String candidateName = entry.getKey();
			Object beanInstance = entry.getValue();

			// resolvableDependencies记录了某个类型对应某个Bean,启动Spring时会进行设置,比如BeanFactory.class对应BeanFactory实例
			// 注意:如果是Spring自己的byType,descriptor.getDependencyName()将返回空,只有是@Autowired才会方法属性名或方法参数名
			if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
					matchesBeanName(candidateName, descriptor.getDependencyName())) {
				return candidateName;
			}
		}
		return null;
	}
  • 首先会找到,所有符合类型的bean,并将beaname和bean封装成一个Map
  • 如果map里元素数量只有一个,会直接确定autowiredBeanName instanceCandidate 
  • 如果有多个就会进行过滤(@Primary/Priority/ByName)
  • 这三个从上到下,有一个能找到就算成功
    • @Primary
    • 这个注解的解析在扫描BD的时候就已经解析了,结果是放到了,BD里面
    • determinePrimaryCandidate的逻辑就是,对根据类型找到的结果循环遍历,找到各自的BD,如果发现有一个标注了Primary,最后就会返回这个bean的beanname,如果发现有多个都标注了,直接抛异常
    • @Priority(不能标注到方法上)
    • 这个就是相当于将根据类型找到的结果进行了排序,根据Priority指定的数字,数字越小,级别越高,最后选出级别最高的那个,最后就会返回这个bean的beanname
    • ByName
    • 循环遍历,对根据类型找到的结果 和  依赖(字段)的描述器里的name进行匹配,找不到就返回空,找的到就返回beanname
  • 这个determineAutowireCandidate的结果如果是空的,就会判断required的值,如果为true,直接抛异常,是false,就返回空(最后注入点注入的就是空)

findAutowireCandidates根据类型获得Map集合
  • 主要 就是 找beanname(因为 如果是原型bean 就不会在单例池里面,所以这个是去BD里面找的)
    • 从BeanFactory中找出和requiredType所匹配的beanName,仅仅是beanName,这些bean不一定经过了实例化,只有到最终确定某个Bean了,如果这个Bean还没有实例化才会真正进行实例化

    • String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());
      • // 从本容器中找
        String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);

      • 这个方法里面,还会去父容器里面找,最后合并(合并的list集合,就算父子容器里面这个类型的beanname 没有重复的)

    • getBeanNamesForType (DefaultListableBeanFactory)怎么找

      • 会有缓存判断 最后掉下面这个方法

      • doGetBeanNamesForTyp(大概意思 -- 就是根据BD 的参数进行类型匹配,然后将这个符合这个类型的 所有 的 beanName 放到一个 字符串的集合中)

  •  找到beanName后 会生成一个result的Map<String, Object>集合

  • 首先会在下面这个集合中 根据类型获得一些bean 但是 从这里取出来的 放到 result集合的key是由Spring生成的(有一定规则,但是不是beanname)

  • 下来就会开始筛选了

  • 会遍历 上面得到的beanname集合,会判断是不是自己注入自己(这个不太合适)

  • isAutowireCandidate 会有三层筛选(责任链模式)

    • SimpleAutowireCandidateResolver 会判断 @Bean(autowireCandidate = true)这个是不是true

    • GenericTypeAwareAutowireCandidateResolver 会进行 泛型判断(这个超级复杂)

    • QualifierAnnotationAutowireCandidateResolver 会对  @Qualifier  的value的值进行判断

    • 三层 过后 会将这个beanname 和 bean 放到 result中

  • 如何经历了这么多 result还是空,这时候才会考虑(自己注入自己)

    • 如果有  会将这个beanname 和 bean 放到 result中

  • 如果也找不到自己注入自己 那就是真的没了

继续过滤 还有三层

如果  findAutowireCandidates 返回的结果中 map 的数据是多个 , 

先判断 @primary 如果有 直接找到返回

再排序  @Priority(1) 通过这个注解 来排序,如果都没标,就会进入到最后一层,如果标了,就是数字越小,优先级越高 ,最高的直接返回

最后一道防线 通过 map的key,也就是byname,将字段名作为key,也就是匹配beanname找到那个对象,找到了就返回,没找到就抛异常

resolveMethodArguments(方法)

@Resource

CommonAnnotationBeanPostProcessor这个类实现的

大体思路(和具体实现的还存在一定的差别)

就是 先找注入点 然后遍历注入点(反射写到bean里面)

这个 是先判断 name  

如果 BD里面存在这个 name 就直接调用getBean方法 

如果不存在 就 再调用 bytype(这个和上面的差不多)

注意  Resource 是java提供的 ,spring只是支持这个注解

Autowired是spring 提供的 

Resource 可能别的框架也支持,换框架时可以减少对代码的修改

性能上 没有什么区别;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值