Spring源码学习(七)-- 依赖注入源码解析(上)

Spring中到底有几种依赖注入的方式?

首先分两种:

  1. 手动注入
  2. 自动注入

手动注入

在XML中定义Bean时,就是手动注入,因为是程序员手动给某个属性指定了值


	

上面这种底层是通过set方法进行注入。


	

上面这种底层是通过构造方法进行注入。

所以手动注入的底层也就是分为两种:

  1. set方法注入
  2. 构造方法注入

自动注入

自动注入又分为两种:

  1. XML的autowire自动注入
  2. @Autowired注解的自动注入

XML的autowire自动注入

在XML中,我们可以在定义一个Bean时去指定这个Bean的自动注入模式:

  1. byType
  2. byName
  3. constructor
  4. default
  5. no

比如:


或者

//@Bean(autowire = Autowire.BY_NAME)
@Bean(autowire = Autowire.BY_TYPE)
public UserServiceImpl userService(){
	return new UserServiceImpl();
}

这么写,表示Spring会自动的给userService中所有的属性自动赋值(不需要这个属性上有@Autowired注解,但需要这个属性有对应的set方法)。

我们看一下源码中是如何实现的,org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

方法中的代码:

int resolvedAutowireMode = mbd.getResolvedAutowireMode();
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;
}

如果我们设置的时byName,执行autowireByName方法:

进来首先执行

String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
获取当前Bean中能进行自动注入的属性名
	protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
		Set 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);
	}

 注意:会有一个BeanDefinition的后置处理(MergedBeanDefinitionPostProcessor,我们可以在这个时候修改BeanDefinition的PropertyValues,告诉BeanDefinition将某个值赋给属性,但是不是直接赋值,相当于是记录一下赋值关系,所以这里有个判断  

 当前BeanDefinition的PropertyValues中没有这个字段才会去自动注入,如果有的话就不会处理,意思就是如果我们自己通过BeanDefinition给某个字段赋值,以我们自己设置为准。

Spring会去解析当前类,把当前类的所有方法都解析出来,Spring会去解析每个方法得到对应的PropertyDescriptor对象,PropertyDescriptor(属性描述器)中有几个属性:

  1. name:这个name并不是方法的名字,而是拿方法名字进过处理后的名字
    1. 如果方法名字以“get”开头,比如“getXXX”,那么name=XXX
    2. 如果方法名字以“is”开头,比如“isXXX”,那么name=XXX
    3. 如果方法名字以“set”开头,比如“setXXX”,那么name=XXX
  2. readMethodRef:表示get方法的Method对象的引用
  3. readMethodName:表示get方法的名字
  4. writeMethodRef:表示set方法的Method对象的引用
  5. writeMethodName:表示set方法的名字
  6. propertyTypeRef:如果有get方法那么对应的就是返回值的类型,如果是set方法那么对应的就是set方法中唯一参数的类型

get方法的定义是: 方法参数个数为0个,并且 (方法名字以"get"开头 或者 方法名字以"is"开头并且方法的返回类型为boolean)

**set方法的定义是:**方法参数个数为1个,并且 (方法名字以"set"开头并且方法返回类型为void)

执行完unsatisfiedNonSimpleProperties会返回当前Bean中能进行自动注入的属性名(是set方法后得到的名字)

然后遍历每个属性名,并去获取Bean对象,并设置到pvs中

Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
// 记录一下propertyName对应的Bean被beanName给依赖了
registerDependentBean(propertyName, beanName);

所以,Spring在通过byName的自动填充属性时流程是:

  1. 找到所有set方法所对应的XXX部分的名字
  2. 根据XXX部分的名字去获取bean

如果我们设置的时byName,执行autowireByType方法,和byName类似

Spring在通过byType的自动填充属性时流程是:

  1. 获取到set方法中的唯一参数的参数类型,并且根据该类型去容器中获取bean
  2. 如果找到多个,会报错。

注意:autowireByName和autowireByType方法都没有直接将得到bean赋值给属性,而是记录到了BeanDefinition的PropertyValues中

pvs.add(propertyName, bean);

同样在实例化完成之后,执行属性赋值之前,会有一个BeanDefinition的后置处理(MergedBeanDefinitionPostProcessor,我们可以在这个时候修改BeanDefinition的PropertyValues,但是同样没有直接赋值给属性,赋值操作是在执行完InstantiationAwareBeanPostProcessor.postProcessProperties(@AutoWired,@Resource)之后

以上,分析了autowire的byType和byName情况,那么接下来分析constructor,constructor表示通过构造方法注入,其实这种情况就比较简单了,没有byType和byName那么复杂。​

如果是constructor,那么就可以不写set方法了,当某个bean是通过构造方法来注入时,spring利用构造方法的参数信息从Spring容器中去找bean,找到bean之后作为参数传给构造方法,从而实例化得到一个bean对象,并完成属性赋值(属性赋值的代码得程序员来写)。

我们这里先不考虑一个类有多个构造方法的情况,后面单独讲推断构造方法。我们这里只考虑只有一个有参构造方法。

其实构造方法注入相当于byType+byName,普通的byType是根据set方法中的参数类型去找bean,找到多个会报错,而constructor就是通过构造方法中的参数类型去找bean,如果找到多个会根据参数名确定。

另外两个:

  1. no,表示关闭autowire
  2. default,表示默认值,我们一直演示的某个bean的autowire,而也可以直接在标签中设置autowire,如果设置了,那么标签中设置的autowire如果为default,那么则会用标签中设置的autowire。

可以发现XML中的自动注入是挺强大的,那么问题来了,为什么我们平时都是用的@Autowired注解呢?而没有用上文说的这种自动注入方式呢?

@Autowired注解相当于XML中的autowire属性的注解方式的替代。这是在官网上有提到的。

Essentially, the @Autowired annotation provides the same capabilities as described in Autowiring Collaborators but with more fine-grained control and wider applicability

翻译一下: 从本质上讲,@Autowired注解提供了与autowire相同的功能,但是拥有更细粒度的控制和更广泛的适用性。

注意:更细粒度的控制

XML中的autowire控制的是整个bean的所有属性,而@Autowired注解是直接写在某个属性、某个set方法、某个构造方法上的。

再举个例子,如果一个类有多个构造方法,那么如果用XML的autowire=constructor,你无法控制到底用哪个构造方法,而你可以用@Autowired注解来直接指定你想用哪个构造方法。

同时,用@Autowired注解,还可以控制,哪些属性想被自动注入,哪些属性不想,这也是细粒度的控制。

但是@Autowired无法区分byType和byName,@Autowired是先byType,如果找到多个则byName。

那么XML的自动注入底层其实也就是:

  1. set方法注入
  2. 构造方法注入

@Autowired注解的自动注入

上文说了@Autowired注解,是byType和byName的结合。

@Autowired注解可以写在:

  1. 属性上:先根据属性类型去找Bean,如果找到多个再根据属性名确定一个
  2. 构造方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个
  3. set方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个

而这种底层到了:

  1. 属性注入
  2. set方法注入
  3. 构造方法注入

Spring源码学习(七)-- 依赖注入源码解析(上)_第1张图片

寻找注入点

在创建一个Bean的过程中,Spring会利用AutowiredAnnotationBeanPostProcessor的**postProcessMergedBeanDefinition()**找出注入点并缓存,执行的时间是在实例化完成之后,执行属性赋值之前,会执行BeanDefinition的后置处理(MergedBeanDefinitionPostProcessor

AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition

@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
  findAutowiringMetadata方法中会解析注入点并放入缓存

Spring源码学习(七)-- 依赖注入源码解析(上)_第2张图片buildAutowiringMetadata找注入点的流程为:

// 遍历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));
				}
			});

 遍历当前类的所有的属性字段Field

查看字段上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该字段是一个注入点

如果字段是static的,则不进行注入

获取@Autowired中的required属性的值

将字段信息构造成一个AutowiredFieldElement对象,作为一个注入点对象添加到currElements集合中。

// 遍历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));
				}
			});

遍历当前类的所有方法Method

判断当前Method是否是桥接方法,如果是找到原方法

查看方法上是否存在@Autowired、@Value、@Inject中的其中任意一个,存在则认为该方法是一个注入点

如果方法是static的,则不进行注入

获取@Autowired中的required属性的值

将方法信息构造成一个AutowiredMethodElement对象,作为一个注入点对象添加到currElements集合中。

do{
    .....
}
while (targetClass != null && targetClass != Object.class);

遍历完当前类的字段和方法后,将遍历父类的,直到没有父类。

最后将currElements集合封装成一个InjectionMetadata对象,作为当前Bean对于的注入点集合对象,并缓存。

static的字段或方法为什么不支持

@Component
@Scope("prototype")
public class OrderService {


}
@Component
@Scope("prototype")
public class UserService  {

	@Autowired
	private static OrderService orderService;

	public void test() {
		System.out.println("test123");
	}

}

看上面代码,UserService和OrderService都是原型Bean,假设Spring支持static字段进行自动注入,那么现在调用两次

  1. UserService userService1 = context.getBean("userService")
  2. UserService userService2 = context.getBean("userService")

问此时,userService1的orderService值是什么?还是它自己注入的值吗?​

答案是不是,一旦userService2 创建好了之后,static orderService字段的值就发生了修改了,从而出现bug。

桥接方法

public interface UserInterface {
	void setOrderService(T t);
}
@Component
public class UserService implements UserInterface {

	private OrderService orderService;

	@Override
	@Autowired
	public void setOrderService(OrderService orderService) {
		this.orderService = orderService;
	}

	public void test() {
		System.out.println("test123");
	}

}

UserService对应的字节码为:

// class version 52.0 (52)
// access flags 0x21
// signature Ljava/lang/Object;Lcom/fztx/service/UserInterface;
// declaration: com/fztx/service/UserService implements com.fztx.service.UserInterface
public class com/fztx/service/UserService implements com/fztx/service/UserInterface {

  // compiled from: UserService.java

  @Lorg/springframework/stereotype/Component;()

  // access flags 0x2
  private Lcom/fztx/service/OrderService; orderService

  // access flags 0x1
  public ()V
   L0
    LINENUMBER 12 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object. ()V
    RETURN
   L1
    LOCALVARIABLE this Lcom/fztx/service/UserService; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x1
  public setOrderService(Lcom/fztx/service/OrderService;)V
  @Lorg/springframework/beans/factory/annotation/Autowired;()
   L0
    LINENUMBER 19 L0
    ALOAD 0
    ALOAD 1
    PUTFIELD com/fztx/service/UserService.orderService : Lcom/zhouyu/service/OrderService;
   L1
    LINENUMBER 20 L1
    RETURN
   L2
    LOCALVARIABLE this Lcom/fztx/service/UserService; L0 L2 0
    LOCALVARIABLE orderService Lcom/fztx/service/OrderService; L0 L2 1
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x1
  public test()V
   L0
    LINENUMBER 23 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "test123"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 24 L1
    RETURN
   L2
    LOCALVARIABLE this Lcom/fztx/service/UserService; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x1041
  public synthetic bridge setOrderService(Ljava/lang/Object;)V
  @Lorg/springframework/beans/factory/annotation/Autowired;()
   L0
    LINENUMBER 11 L0
    ALOAD 0
    ALOAD 1
    CHECKCAST com/fztx/service/OrderService
    INVOKEVIRTUAL com/fztx/service/UserService.setOrderService (Lcom/fztx/service/OrderService;)V
    RETURN
   L1
    LOCALVARIABLE this Lcom/fztx/service/UserService; L0 L1 0
    MAXSTACK = 2
    MAXLOCALS = 2
}

可以看到在UserSerivce的字节码中有两个setOrderService方法:

  1. public setOrderService(Lcom/Fztx/service/OrderService;)V
  2. public synthetic bridge setOrderService(Ljava/lang/Object;)V

并且都是存在@Autowired注解的。​

所以在Spring中需要处理这种情况,当遍历到桥接方法时,得找到原方法。

注入点进行注入

Spring在AutowiredAnnotationBeanPostProcessor的**postProcessProperties()**方法中,会遍历所找到的注入点依次进行注入。​时间节点在执行完实例化后(InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation)并且在处理完spring自带的依赖注入之后。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean中:

boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			// 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
			// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
			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;
				}
			}
		}

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;
	}

首先也是去寻找注入点,但是这个时候可以直接从缓存中取到

InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);

metadata.inject(bean, beanName, pvs)对注入点进行依赖注入:

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		Collection checkedElements = this.checkedElements;
		Collection elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			// 遍历每个注入点进行依赖注入
			for (InjectedElement element : elementsToIterate) {
				element.inject(target, beanName, pvs);
			}
		}
	}

遍历每个注入点进行依赖注入,注意注入点有属性也有方法,所以循环的InjectedElement会有两个具体的实现类AutowiredFieldElement(属性),AutowiredMethodElement(方法)

 Spring源码学习(七)-- 依赖注入源码解析(上)_第3张图片

 所以当执行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) {
				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);
			}
			if (value != null) {
				// 反射给filed赋值
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}

 resolveFieldValue(field, bean, beanName)方法根据filed从BeanFactory中查到的匹配的Bean对象:

1.将对应的字段封装为DependencyDescriptor对象

DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());

2.调用BeanFactory的resolveDependency()方法,传入DependencyDescriptor对象,进行依赖查找,找到当前字段所匹配的Bean对象。

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

3.将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortcutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建该Bean时,就可以直接拿缓存的结果对象beanName去BeanFactory中去那bean对象了,不用再次进行查找了

                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;
				}

4.利用反射将结果对象赋值给字段。

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

Set方法注入

AutowiredMethodElement#inject

		@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();
				}
			}
		}

如果pvs中已经有当前注入点的值了,则跳过注入

if (checkPropertySkipping(pvs)) {
	return;
}

resolveMethodArguments(method, bean, beanName)方法:

1.遍历将对应的方法的参数,将每个参数封装成MethodParameter对象

2.将MethodParameter对象封装为DependencyDescriptor对象

 3.调用BeanFactory的resolveDependency()方法,传入DependencyDescriptor对象,进行依赖查找,找到当前方法参数所匹配的Bean对象。

Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);

4.将DependencyDescriptor对象和所找到的结果对象beanName封装成一个ShortcutDependencyDescriptor对象作为缓存,比如如果当前Bean是原型Bean,那么下次再来创建该Bean时,就可以直接拿缓存的结果对象beanName去BeanFactory中去那bean对象了,不用再次进行查找了

Spring源码学习(七)-- 依赖注入源码解析(上)_第4张图片

5.利用反射将找到的所有结果对象传给当前方法,并执行。

 Spring源码学习(七)-- 依赖注入源码解析(上)_第5张图片

 执行完InstantiationAwareBeanPostProcessor.postProcessProperties(@AutoWired,@Resource)之后会执行:

// 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
if (pvs != null) {
	applyPropertyValues(beanName, mbd, bw, pvs);
}

将BeanDefinition中设置的PropertyValues,去赋值到Bean中。

断点调试

UserService:

@Service
public class UserService {

	@Autowired
	private OrderService orderService;

	public void setOrderService(OrderService orderService) {
		this.orderService = orderService;
	}
	public void sayHi() {
		System.out.println(orderService);
	}


}

自定义MergedBeanDefinitionPostProcessor实现类:

@Component
public class FztxMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
		if ("userService".equals(beanName)) {
			beanDefinition.getPropertyValues().add("orderService", new OrderService());
		}
	}
}

首先在UserService的属性orderService上添加@AutoWired注解,同时我们自定义MergedBeanDefinitionPostProcessor实现类设置BeanDefinition的PropertyValues给orderService赋值,我们通过断点调试一下:

执行完BeanDefinition后置处理,执行AutowiredAnnotationBeanPostProcessor的postProcessProperties方法之前:

BeanDefinition中的PropertyValues设置的orderService是OrderService@1746(自定义MergedBeanDefinitionPostProcessor实现类中new的OrderService)

Spring源码学习(七)-- 依赖注入源码解析(上)_第6张图片

 但我们bean对象中的orderService还是null,此时还没有进行注入点注入

Spring源码学习(七)-- 依赖注入源码解析(上)_第7张图片

接下来执行AutowiredAnnotationBeanPostProcessor的postProcessProperties方法,@AutoWired注解进行注入:

Spring源码学习(七)-- 依赖注入源码解析(上)_第8张图片

 此时userService对象中的orderService属性值是OrderService@1777(spring容器中的orderservice对象)

接下来执行applyPropertyValues(beanName, mbd, bw, pvs)处理BeanDefinition中设置的PropertyValues,执行完之后:

 此时userService对象中的orderService属性值是OrderService@1746,也就是我们自定义自定义MergedBeanDefinitionPostProcessor实现类中new的OrderService

总结

1.BeanDefinition后置处理,执行MergedBeanDefinitionPostProcessor实现类的postProcessMergedBeanDefinition()方法,在这一步会调用AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition()方法去寻找注入点(@Autowired、@Value、@Inject)并缓存,同时我们也可以自己定义MergedBeanDefinitionPostProcessor实现类来设置BeanDefinition的PropertyValues(必须要有set方法

2.处理spring自带的依赖注入,就是上面说的XML或者@Bean设置的的autowire自动注入(byType、byName)--spring标记为过期的,在这一步获取当前Bean中能进行自动注入的属性名,拿到对应的bean,设置到BeanDefinition的PropertyValues(如果之前PropertyValues有某个属性名,这一步则不处理)

3.执行InstantiationAwareBeanPostProcessor实现类的postProcessProperties方法,在这一步会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法对注入点进行注入,会直接给对象中的属性赋值,并不会处理BeanDefinition的PropertyValues,直接返回了;同时也会调用CommonAnnotationBeanPostProcessor的postProcessProperties()方法对@Resource注解进行处理

4.将BeanDefinition中设置的PropertyValues,去赋值给对象中的属性(如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired)

以上是关于Spring中的自动注入(byName,byType)和@Autowired注解的工作原理以及源码分析,下篇文章会分析一下其中的一些方法:BeanFactory的resolveDependency()方法,传入DependencyDescriptor对象,进行依赖查找,找到当前字段所匹配的Bean对象;以及@Resource和@Qualifier等注解

你可能感兴趣的:(Spring源码,spring,java,源码)