• spring5.3 六:依赖注入源码分析上


    spring5.3 六:依赖注入源码分析上

    之前分析了bean的生命周期各个阶段,下面针对自动注入和属性填充这个阶段进行详细分析。先来看下这部分源码

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    		if (bw == null) {
    			if (mbd.hasPropertyValues()) {
    				throw new BeanCreationException(
    						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
    			}
    			else {
    				// Skip property population phase for null instance.
    				return;
    			}
    		}
    
    		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    		// state of the bean before properties are set. This can be used, for example,
    		// to support styles of field injection.
    		// 实例化之后,属性设置之前
    		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    					return;
    				}
    			}
    		}
    		//这个if 会根据配置的AUTOWIRE_BY_NAME 还是 AUTOWIRE_BY_TYPE 进行属性注入
    		//但是这跟AUTOWIRE注解没有关系  一般来说也不会进入到这个方法中 基本可以忽略
    		//PropertyValues 是RootBeanDefinition的一个属性
    		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    		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) {
    				//大致过程:找到bean当中需要属性注入的属性  然后记录到RootBeanDefinition的PropertyValues属性中
    				autowireByName(beanName, mbd, bw, newPvs);
    			}
    			// Add property values based on autowire by type if applicable.
    			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    				//和上面ByName方法类似
    				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();
    			}
    			//从这里开始处理@Autowired和@Resource
    			// 处理@Autowired 的是AutowiredAnnotationBeanPostProcessor
    			// 处理@Resource 的是CommonAnnotationBeanPostProcessor
    			//它们都是InstantiationAwareBeanPostProcessor的实现类
    			//开始遍历InstantiationAwareBeanPostProcessor这个接口的实现类
    			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    				// 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
    				// AutowiredAnnotationBeanPostProcessor在调用postProcessProperties()之前会先调用postProcessMergedBeanDefinition方法
    				//AutowiredAnnotationBeanPostProcessor 不仅实现了InstantiationAwareBeanPostProcessor 也实现了MergedBeanDefinitionPostProcessor
    				//而postProcessMergedBeanDefinition 是MergedBeanDefinitionPostProcessor 提供的接口
    				// 而MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition是处理合并后的BeanDefinition,
    				// 也就是在在实例化后这个步骤前进行调用,那么自然也就在属性赋值前就已经调用了
    				// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
    				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    				if (pvsToUse == null) {
    					if (filteredPds == null) {
    						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    					}
    					pvsToUse = bp.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);
    		}
    
    		// 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
    		if (pvs != null) {
    			//进行属性赋值
    			applyPropertyValues(beanName, mbd, bw, pvs);
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    这段代码主要分为两个部分,一个部分是spring自己的自动注入,就是这个if if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE)。另一部分是注解的形式例如@Autowired和@Resource。
    先来看第一部分

    spring的自动注入

    这一部分的内容都在if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE)这个if当中,这部分的代码和@Autowired和@Resource无关,什么时候会执行这部分的代码呢?如下图
    在这里插入图片描述
    这种方式已经过期了。稍微了解就好。以BY_NAME作为例子,那么就会进入到autowireByName(beanName, mbd, bw, newPvs);这个方法中

    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)) {
    				//通过getBean方法通过名称获取到对应的bean
    				Object bean = getBean(propertyName);
    				//将找到的bean对象保存到pvs当中 并没有直接赋值  这个对象是上面getBean方法返回的
    				// 比如说有个User对象需要注入 那么getBean返回的就是user对象 但是并没有直接赋值而是保存起来
    				pvs.add(propertyName, bean);
    				// 记录一下propertyName对应的Bean被beanName给依赖了
    				registerDependentBean(propertyName, beanName);
    				if (logger.isTraceEnabled()) {
    					//忽略
    			}
    			else {
    				//忽略
    			}
    		}
    	}
    
    protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
    		Set<String> result = new TreeSet<>();
    		PropertyValues pvs = mbd.getPropertyValues();
    		//属性描述 set get方法的属性相关信息  比如说 set get方法名  属性名等等
    		PropertyDescriptor[] pds = bw.getPropertyDescriptors();
    		// 什么样的属性能进行自动注入?
    		// 1.该属性有对应的set方法   pd.getWriteMethod() != null
    		// 2.没有在ignoredDependencyTypes中
    		// 3.如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
    		// 4.属性类型不是简单类型,比如int、Integer、int[]    !BeanUtils.isSimpleProperty(pd.getPropertyType())
    		// 5.BeanDefinition中的PropertyValues 中不包含这个属性 !pvs.contains(pd.getName()) 如果包含了说明之前人为的进行赋值操作
    		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);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    这部分内容就是说当类型设置为Autowire.BY_NAME时,就会进入autowireByName方法,然后通过unsatisfiedNonSimpleProperties方法找到那些属性是需要自动注入的,说白了就是找set方法,set后面的名称就是属性名称,遍历所有找到的名称通过getBean方法获取对应的bean然后放入到RootBeanDefinition。
    autowireByType也类似,找到所有需要自动注入的属性名称后在找到对应的类型,然后根据类型找到对应的bean放入到RootBeanDefinition中。最后真正赋值的操作是applyPropertyValues(beanName, mbd, bw, pvs);这部分。

    @Autowired自动注入

    @Autowired注解可以写在:

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

    从开头的populateBean源码来看@Autowired和@Resource的自动注入根据InstantiationAwareBeanPostProcessor的子类来实现的。

    @Autowired实现的子类是AutowiredAnnotationBeanPostProcessor
    @Resource实现的子类是CommonAnnotationBeanPostProcessor

    AutowiredAnnotationBeanPostProcessor实现了SmartInstantiationAwareBeanPostProcessorMergedBeanDefinitionPostProcessor等接口,其中MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法在BeanDefinition后置处理是就执行。InstantiationAwareBeanPostProcessor的postProcessProperties方法就是在这个阶段执行,也就是说先执行postProcessMergedBeanDefinition方法。

    @Override
    	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    		//找注入点
    		//大致过程:根据beanName 找到类对象 对类对象处理 找到符合条件的属性和方法
    		//把找到的注入点缓存起来
    		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    		metadata.checkConfigMembers(beanDefinition);
    	}
    //findAutowiringMetadata的核心代码是buildAutowiringMetadata(clazz)
    private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    		//判断这个类需不需要找注入点 想String这种类型就不需要找注入点
    		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
    			return InjectionMetadata.EMPTY;
    		}
    		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    		Class<?> targetClass = clazz;
    		//这个do while 中分为两个大步骤
    		do {
    			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    			// 1.遍历targetClass中的所有Field 每个Field执行lambda
    			ReflectionUtils.doWithLocalFields(targetClass, field -> {
    				// field上是否存在@Autowired、@Value、@Inject中的其中一个
    				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
    				if (ann != null) {
    					// ann != null 说明这个field有 上面三个注解之一
    					// 继续判断 如果这个field是static类型的 那么filed不是注入点,不会进行自动注入
    					//为什么静态不注入  从原型bean角度考虑
    					if (Modifier.isStatic(field.getModifiers())) {
    						if (logger.isInfoEnabled()) {
    							logger.info("Autowired annotation is not supported on static fields: " + field);
    						}
    						return;
    					}
    
    					// 专门处理@Autowired的required的值
    					boolean required = determineRequiredStatus(ann);
    					//把这个注入点封装成AutowiredFieldElement 添加到currElements中
    					currElements.add(new AutowiredFieldElement(field, required));
    				}
    			});
    
    			// 2.遍历targetClass中的所有Method 每个方法执行lambda
    			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);
    						}
    					}
    					//同样解析@Autowired的required的值
    					boolean required = determineRequiredStatus(ann);
    					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    					//把这个注入点封装成AutowiredMethodElement 添加到currElements中
    					currElements.add(new AutowiredMethodElement(method, required, pd));
    				}
    			});
    			//把所有符合上面条件的Feild 和 method 放入到elements 中
    			elements.addAll(0, currElements);
    			//然后遍历父类 如果没有父类 那么while条件就不满足 退出循环
    			targetClass = targetClass.getSuperclass();
    		}
    		while (targetClass != null && targetClass != Object.class);
    		return InjectionMetadata.forElements(elements, clazz);
    	}
    
    	@Nullable
    	private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
    		MergedAnnotations annotations = MergedAnnotations.from(ao);
    		//判断获取到注解符不符合autowiredAnnotationTypes ,autowiredAnnotationTypes这是个集合
    		// 在创建AutowiredAnnotationBeanPostProcessor的时候 会调用AutowiredAnnotationBeanPostProcessor的构造方法
    		// 这个构造方法就会对autowiredAnnotationTypes 进行赋值 传入@Autowired @Value @Inject
    		for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
    			MergedAnnotation<?> annotation = annotations.get(type);
    			if (annotation.isPresent()) {
    				//return 就表示了只要找到上面三个注解中某一个就会直接返回
    				return annotation;
    			}
    		}
    		return null;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

    总的来说在BeanDefinition后置处理的阶段会先执行AutowiredAnnotationBeanPostProcessorpostProcessMergedBeanDefinition方法。这个方法主要是找注入点(被@vaule、@Autowired标注的属性和方法)。是怎么找的呢?
    过滤掉String、Integer等简单的类型。遍历每个类型的属性和方法通过findAutowiredAnnotation找到注入点。把所有注入点都找到封装成一个对象放入到list中。
    到了属性自动注入阶段执行AutowiredAnnotationBeanPostProcessorpostProcessProperties方法。

    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    		// 找注入点(所有被@Autowired注解了的Field或Method)
    		// 把在BeanDefinition后置处理的阶段找到的注入点在拿出来
    		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;
    	}
    
    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) {
    				element.inject(target, beanName, pvs);
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在这里插入图片描述
    第一个是给属性赋值的,第二个是给方法赋值的
    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) {
    				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);
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    AutowiredMethodElement

    		@Override
    		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    			//当前bean的BeanDefinition的PropertyValues属性 有没有当前注入点的值  大概是这个意思吧
    			//  没太搞懂 只是个判断 不管了
    			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();
    				}
    			}
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    通过上述的inject方法最后都是通过反射进行赋值。到此依赖注入部分就分析完了,但是如何根据属性找到具体的bean和如何根据方法找到对应的参数下篇在分析。

  • 相关阅读:
    AWTK 支持可独立安装的小应用程序 (applet)
    深度学习中的偏差、方差、正则化
    mapstruct更新现有实体忽略null空值
    [ARC098F] Donation(找性质+点 Kruskal 重构树)
    STM32 Cube配置RS485 Modbus
    源码解析:面试必问的LinkedList,看这篇文章就够了
    神经网络是参数模型吗,神经网络的参数计算
    解决navicat premium连接数据库自动断开问题
    Java面试--死锁
    如何使用libavfilter库给pcm音频采样数据添加音频滤镜?
  • 原文地址:https://blog.csdn.net/admin522043032/article/details/125891760