Spring源码解析——依赖注入(一)

概述

手动注入
  • set方法
  • 构造方法
自动注入
  • XML的autowire自动注入
  • @Autowired注解的自动注入(只是一个注解,基于byType注册模式实现,算不上真正的自动注入

XML的注入方式

xml的注入方式在最早的时候用的最多的,xml的注入分为手动模式和自动模式,我们先来看下手动的模式,手动模式要在xml文件中写标签来手动注入

<bean name="orderService" class="com.zy.service.OrderService">

</bean>
<bean name="userService" class="com.zy.service.UserService">
   <property name="orderService" ref="orderService"/>
</bean>

对应的要在UserService提供set方法

public class UserService {


   private OrderService orderService;
   public void setOrderService(OrderService orderService) {
      this.orderService = orderService;
   }

   public void test(){
      System.out.println("orderService="+ orderService);
   }
}

这样就可以注入了,我们看下这种手动模式在spring的源码中是如何处理的,在spring填充属性的populateBeang方法中,代码简化

		//spring扫描的阶段会将你配置的<Property />标签扫描成一个PropertyValue
		//然后最后在初始化实例化bean过后就是填充属性的这个方法applyPropertyValues会将找到的bean填充到bean的属性中,也就是注入到bean的属性中;
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();

		//如果说xml的方式要通过自动注入
		//注入模式有4种,no、byType、byName、constructor
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			// by_name是根据根据属性名字找bean
			// by_type是根据属性所对应的set方法的参数类型找bean
			// 找到bean之后都要调用set方法进行注入

			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;

			// 总结一下
			// 其实就是Spring自动的根据某个类中的set方法来找bean,byName就是根据某个set方法所对应的属性名去找bean
			// byType,就是根据某个set方法的参数类型去找bean
			// 注意,执行完这里的代码之后,这是把属性以及找到的值存在了pvs里面,并没有完成反射赋值
		}

		

		if (pvs != null) {
			// pvs存的就是属性已经对应的值
			//xml 手动注入
			applyPropertyValues(beanName, mbd, bw, pvs);
		}

如果想实现自动注入则在配置中的bean标签上加autowire="byType"或者在beans标签中设置一个全局的属性default-autowire

接下来看看xml自动注入源码实现

// 是否在BeanDefinition中设置了属性值
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		//得到在xml中配置的autowire属性值,比如配置了autowire="byType",那么resolvedAutowireMode就会有值2
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			
			//先声明一个MutablePropertyValues,把原来的PropertyValues传进去,如果pvs为空,则构建一个list集合
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				//这个是以byName进行注入,bw是包装的bean对象,mbd是BeanDefinition,newpvs是属性注入的对象
				//byName:根据bean找到bean下面的所有set方法,比如setUserService,那么会截取set得到userService,然后去
				//bd中找,如果找到了,然后进注入到pvs中,在本方法的最后applyPropertyValues进入设置属性进去
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				//byType里面处理的逻辑有点复杂,我看了下,实现原理大概如下:
				//1.先根据bean所在的类找到所有的set方法,然后得到set方法对应的名字,也就是beanName集合
				//然后循环这个集合,将beanName装载成一个属性描述器,然后根据属性描述器得到方法参数对象MethodParameter
				//2.然后在根据MethodParameter封装成一个byType的依赖描述器,请注意,只有byType才实行了依赖描述器的实现类
				//byName是没有的,封装成一个byType的依赖描述器过后,根据这个依赖描述器获取bean,简单来说,就是你ref=“bean”中的
				//bean在容器中的bean对象信息,那出来然后注入到newpvs中,在下面的applyPropertyValues方法填充进去
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;

			// 总结一下
			// 其实就是Spring自动的根据某个类中的set方法来找bean,byName就是根据某个set方法所对应的属性名去找bean
			// byType,就是根据某个set方法的参数类型去找bean
			// 注意,执行完这里的代码之后,这是把属性以及找到的值存在了pvs里面,并没有完成反射赋值
		}

autowireByName(beanName, mbd, bw, newPvs)

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

		// 找到有对应set方法的属性
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				// 根据属性名去找bean,这就是byName
				Object bean = getBean(propertyName);
				// 给属性赋值
				pvs.add(propertyName, bean);
				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");
				}
			}
		}
	}

//------------------------------------------------------------------------------------------
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
		Set<String> result = new TreeSet<>();
		PropertyValues pvs = mbd.getPropertyValues(); // 在BeanDefinition中添加的属性和值,
		//获取所有属性,比如setUserService,那么会截取set得到userService
		PropertyDescriptor[] pds = bw.getPropertyDescriptors();

		// 对类里所有的属性进行过滤,确定哪些属性是需要进行自动装配的
		for (PropertyDescriptor pd : pds) {
			// 属性有set方法,并且
			// 没有通过DependencyCheck排除,并且
			// 没有在BeanDefinition中给该属性赋值,并且
			// 属性的类型不是简单类型
			if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
					!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
				result.add(pd.getName());
			}
		}

		// 返回过滤之后的结果,后续只对这些属性进行自动装配
		return StringUtils.toStringArray(result);
	}

//----------------------------------------------------------------------------------------
public PropertyDescriptor[] getPropertyDescriptors() {
		return getCachedIntrospectionResults().getPropertyDescriptors();
	}
PropertyDescriptor[] getPropertyDescriptors() {
		PropertyDescriptor[] pds = new PropertyDescriptor[this.propertyDescriptorCache.size()];
		int i = 0;
		for (PropertyDescriptor pd : this.propertyDescriptorCache.values()) {
			pds[i] = (pd instanceof GenericTypeAwarePropertyDescriptor ? pd :
					buildGenericTypeAwarePropertyDescriptor(getBeanClass(), pd));
			i++;
		}
		return pds;
	}
private PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(Class<?> beanClass, PropertyDescriptor pd) {
		try {
			return new GenericTypeAwarePropertyDescriptor(beanClass, pd.getName(), pd.getReadMethod(),
					pd.getWriteMethod(), pd.getPropertyEditorClass());
		}
		catch (IntrospectionException ex) {
			throw new FatalBeanException("Failed to re-introspect class [" + beanClass.getName() + "]", ex);
		}
	}
Method candidate = ClassUtils.getMethodIfAvailable(
					this.beanClass, "set" + StringUtils.capitalize(getName()), (Class<?>[]) null);

autowireByType(beanName, mbd, bw, newPvs)

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

		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}

		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);

		// 找到有对应set方法的属性
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			try {
				PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
				// Don't try autowiring by type for type Object: never makes sense,
				// even if it technically is a unsatisfied, non-simple property.
				//这里是判断是你的属性描述器,也就是说你的set方法的参数的类型不能是Object
				//因为如果setUserService(Object userService),那么像这个方法,如果是Object,spring根本不知道你要注入那个bean
				//所以不能是Object
				if (Object.class != pd.getPropertyType()) {
					// set方法中的参数信息
					//根据属性描述器获取这个set方法的参数信息
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
					// Do not allow eager init for type matching in case of a prioritized post-processor.
					boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);

					/**
					 *
					 * 根据方法的参数MethodParameter获取一个bean
					 * 到这里知道这个方法是byType,byType的原理是根据你的set方法的参数类型得到一个bean,所以这里是通过
					 * set方法的参数比如setUserService(UserService uservice)中的UserService来构建一个依赖描述器
					 * 这个依赖描述器得到过后,根据这个依赖描述器和其他一些参数得到一个bean
					 */
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);

					// 根据类型找bean,这就是byType
					//简单来说就是根据依赖描述器通过下面这个方法得到一个Bean,然后注入到pvs中
					//后面说
					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
					if (autowiredArgument != null) {
						pvs.add(propertyName, autowiredArgument);
					}
					for (String autowiredBeanName : autowiredBeanNames) {
						registerDependentBean(autowiredBeanName, beanName);
						if (logger.isTraceEnabled()) {
							logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
									propertyName + "' to bean named '" + autowiredBeanName + "'");
						}
					}
					autowiredBeanNames.clear();
				}
			} catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
			}
		}
	}

xml的自动注入看上面的源码分析都是不会马上注入,而是添加到pvs中,最后调用applyPropertyValues方法进行属性填充的,所以我们这里总结出一个结论就是
spring 的xml方式注入依赖,分为手动和自动,手动的时候spring会将属性扫描到pvs中,然后如果是自动的话,自动获取的属性对应关系也会放入pvs中,最后调用applyPropertyValues进行属性填充。

spring的注解依赖注入

sprng的注解方式@AutoWired注入模式和上面的不太一样,@AutoWired有三种注入模式:
1.属性注入
2.非静态方法注入
3.构造方法注入
这里只讲前两种,第三中在后面讲,@AutoWired注入分为两步,

  1. 第一步是找到注入点,然后放入缓存,
  2. 第二步是从缓存获取注入点进行注入,spring中的依赖注入@AutoWired也是通过AutowiredAnnotationBeanPostProcessor这个bean后置处理器实现的,这个后置处理器中提供了两个方法,spring分别是在实例化后初始化前调用,这两个方法是postProcessMergedBeanDefinition和postProcessProperties,其中postProcessMergedBeanDefinition是找到bena的注入点,而postProcessProperties是进行注入,先来看下如何找到注入点的源码,注入点的源码是在doCreateBean中实现的。
doCreateBean之注入点
synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					// 运行修改合并好了的BeanDefinition
					// 这里会查找@Autowired的注入点(InjectedElement),并把这些注入点添加到mbd的属性externallyManagedConfigMembers中
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				} catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

//--------------------------------------------------------------------------------------------


protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof MergedBeanDefinitionPostProcessor) {
				MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
				bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
			}
		}
	}

后置处理器中调用的是postProcessMergedBeanDefinition,这个后置处理器是在AutowiredAnnotationBeanPostProcessor,所以我们看下AutowiredAnnotationBeanPostProcessor类中的注入点代码

@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		//找到所有的注入点@AutoWired
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

//------------------------------------------------------------------------------------------------

	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.
		/**
		 * 先从缓存中获取,如果缓存中没有,就去根据bean的类去找到,找到过后注入到injectionMetadataCache缓存中
		 * 我们知道@AutoWired注入可以通过属性、普通方法、构造进行注入,这里对属性和普通方法进行注入
		 */
		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);
					}
					// 寻找当前clazz中的注入点,把所有注入点整合成为一个InjectionMetadata对象
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

//-------------------------------------------------------------------------------------------

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {

		// 判断是不是候选者类,比如说类名,如果是以"java."开头的则不是候选者类
		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<>();

			// 遍历属性,看是否有@Autowired,@Value,@Inject注解
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				// 如果存在@Autowired,@Value,@Inject注解其中一个
				if (ann != null) {
					// 如果字段是static的,则直接进行返回,不进行注入
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					// 是否required
					boolean required = determineRequiredStatus(ann);
					// 生成一个注入点AutowiredFieldElement
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			// 遍历方法,看是否有@Autowired,@Value,@Inject注解
			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;
					}
					// 方法参数值为0,不能用来注入属性
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					// 看是否有@required注解
					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);

		// 所有能够注入的属性集合对应的InjectionMetadata对象
		return InjectionMetadata.forElements(elements, clazz);
	}

//---------------------------------------------------------------------------------------------

@Nullable
	private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
		// 查看当前字段上是否存在@Autowired,@Value,@Inject注解,存在其中一个则返回,表示可以注入
		MergedAnnotations annotations = MergedAnnotations.from(ao);
		// autowiredAnnotationTypes是一个LinkedHashSet,所以会按顺序去判断当前字段中是否有Autowired注解,如果有则返回
		// 如果没有Autowired注解,那么则判断是否有Value注解,在判断是否有Inject注解
		for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
			MergedAnnotation<?> annotation = annotations.get(type);
			if (annotation.isPresent()) {
				return annotation;
			}
		}
		return null;
	}

  1. spring在这个后置处理器中提供了两种方式的依赖注入,属性注入和普通非静态方法的注入;
  2. 首先根据传过来的bean,找到所有的声明的属性和方法,然后循环这个类,因为这个类可能有父类,找寻要找到所有的父类中看是否有注入的属性和方法,是根据是否实现了@AutoWired来找的;
  3. 如果找到了属性或者方法,那么如果是属性,就构造一个对象AutowiredFieldElement 或者AutowiredMethodElement,放入缓存,属性对象和方法对象都实现了InjectionMetadata.InjectedElement,所以这两个对象中都实现了inject方法,用来后面注入的。
  4. InjectElement就是注入的对象点,也就是需要依赖注入的属性或者方法都保存在InjectElement里面,我们来看下InjectElement这个对象的结构:
/**
 * A single injected element.
 * 注入点,spring的依赖注入的注入点就是InjectedElement
 * member可以是Field或者Method
 */
public abstract static class InjectedElement {

   //注入的成员类型,Field或者Member
   protected final Member member;
       //注入点是否是属性Field
   protected final boolean isField;

   //属性的描述器,如果是属性注入的注入点,那么这个pd值是空的,只有方法的注入才有
   @Nullable
   protected final PropertyDescriptor pd;

   @Nullable
   protected volatile Boolean skip;

   protected InjectedElement(Member member, @Nullable PropertyDescriptor pd) {
      //member中可以是Field可以是method
      this.member = member;
      this.isField = (member instanceof Field);
      this.pd = pd;
   }
   ......

其中member可以是属性可以是方法,就根据你存入的是AutowiredMethodElement还是AutowiredFieldElement;
5. 最后找到的所有注入点都缓存到对象private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256)中;

@AutoWired依赖注入

@AutoWired的依赖注入也是在bean的后置处理器中实现的,具体的代码是在populateBean这个方法里面,代码片段如下:

/**
			 * 这里调用的又是bean的后置处理器,这里的后置处理器是在bean属性填充过后的bean后置处理器
			 * 这个后置处理器现在用的最多,spring内部定义的InstantiationAwareBeanPostProcessor实现了这个接口,主要处理的是
			 * @AutoWired的后置处理器,依赖注入的在这里调用的,最重要的是postProcessProperties这个方法
			 * 所以InstantiationAwareBeanPostProcessor的后置处理器方法postProcessProperties是处理@AutoWired @Resource注解的
			 * 具体来说就是:
			 * @AutowiredannotationBeanPostProcessor处理的是@AutoWired、@Value,@Inject注解
			 * @CommonAnnotationBeanPostProcessor处理的是@Resource注解
			 * 都是在postProcessProperties方法中处理的
			 */
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

					// 调用BeanPostProcessor分别解析@Autowired、@Resource、@Value,得到属性值
					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;
				}
			}

主要是调用后置处理器中的方法postProcessProperties

@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		// InjectionMetadata中保存了所有被@Autowired注解标注的属性/方法并封装成一个个的InjectedElement
		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;
	}

上面的代码的inject是根据是属性注入还是方法注入调用具体的方法,AutowiredFieldElement中的inject方法和AutowiredMethodElement中的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) {
				if (logger.isTraceEnabled()) {
					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
				}
				// element可能是Method,也可能是Field
				element.inject(target, beanName, pvs);
			}
		}
	}

AutowiredFieldElement中的inject

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				// 当前注入点已经注入过了,有缓存了,则利用cachedFieldValue去找对应的bean
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				//  Spring在真正查找属性对应的对象之前, 会先将该属性的描述封装成一个DependencyDescriptor, 里面保存了Filed、是否强制需要即required, 以及属性所在的类(即Field所在的类Class对象)
				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 {
					// 根据field去寻找合适的bean
					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;
							// 注册当前bean依赖了哪些其他的bean的name
							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);
			}
		}
	}

AutowiredMethodElement中的inject

@Override
		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 {
				//得到方法参数的个数,并且封装一个Object arguments
				int argumentCount = method.getParameterCount();
				//这个数组存放的是每个参数对应的bean在spring容器中的bean对象
				arguments = new Object[argumentCount];
				DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];

				// 记录自动注入的beanName
				Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				// 遍历当前set方法中的每个参数,将方法参数
				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 {
						// 寻找bean
						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);
					}
				}

				// arguments中存储的就是所找到的bean对象,构造为ShortcutDependencyDescriptor进行缓存
				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();
				}
			}
		}
  1. 从缓存中获取注入点,然后开始循环注入点;

  2. 如果是属性的注入点,那么就调用AutowiredFieldElement中的inject方法,在该方法中处理不用看spring源码大家也能知道,无非就是通过反射对feild进行赋值,也就是set方法区赋值,但是这里有点重要的点就是spring的@AutoWired是先byType,在byName的,什么意思呢?在注入的方法中有个方法特别重要就是resolveDependency,这个方法就是根据你注入的属性去spring的容器中找到对应的bean;比如我们有个属性是private UserService userservice;那么spring会根据userserivce去spring容器中找到,找到了直接返回,然后调用field.set进行注入赋值;但是在这个过程中spring的处理方式是:
    先根据byType,也就是你的UserService找到对应的bean对象列表,这个时候分为三种情况:
    1).如果为空,则证明在spring容器中不存在这个bean,如果这个时候你的@AutoWired设置了required属性,并且为false,那么就注入不成功;
    2).如果不为空,只有一条数据,则证明在容器中已经找到了相对应的bean,直接返回注入就可了。
    3).如果返回多条,则证明在容器中存在多个相同的Bean对象,那么这个时候就要开始byName,根据字段的byName得到唯一的一个Bean,所以spring的@AutoWired依赖注入是先byType,在byName的。

  3. 如果是方法的注入点,那就调用AutowiredMethodElement中的inject方法,找bean的方式和属性的是一样的,我只是说byType和byName的方式和属性的是一样的,一样的调用了resolveDependency这个方法;但是方法的注入和属性注入不一样,比如我的注入方法如下:

public void setxxx(UserService userServie){
     .....
}
public void setxxx(UserService userServie,OrderService){
     .....
}

所以方法注入的要看方法的参数,所以spring的方法注入需要遵循两点:

  1. 方法的参数不能为空,为空谈何注入;
  2. 方法必须是普通的非静态方法。
    那么spring会构建一个arguments数组,然后获取每个参数,然后根据参数去spring容器中找bean,找bean的过程也是先byType再byName,找到过后赋值给arguments[i]=object,最后找到了所有的参数对应的bean过后,执行
    method.invoke(target,arguments)进行反射调用方法注入进行注入。
    在这里插入图片描述

参考

https://note.youdao.com/ynoteshare1/index.html?id=6f388df56f77781bd2c9b4e269d558c7&type=note

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值