Spring bean 成员属性/成员方法参数依赖注入分析

本文详细解析了Spring框架中成员属性依赖及成员方法参数依赖的注入过程。通过源代码分析,介绍了依赖注入的具体实现,包括AutowiredAnnotationBeanPostProcessor、InjectionMetadata及InjectedElement等关键组件的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

对于一个bean中成员属性方式的依赖和成员方法参数方式的依赖,会在这个bean创建过程中属性填充阶段对这些依赖进行依赖注入。具体地讲,这两种形式的依赖如下例子所示 :

@Component
public class BeanA {}
@Component
public class BeanB {}
@Component
public class DemoBean {
    
    // 成员属性依赖
    @Autowired;
    private BeanA a;
    
    
    // 成员方法参数依赖
    private BeanB b;    
    @Autowired
    public void setB(BeanB b){
        this.b=b;
    }
    
    // 成员属性依赖
    @Value("#{city}")
    private String c;
}

bean属性填充的大致位置位于 :

AbstractBeanFactory#getBean
=> AbstractBeanFactory#doGetBean
=> DefaultSingletonBeanRegistry#getSingleton
=> AbstractAutowireCapableBeanFactory#createBean
=> AbstractAutowireCapableBeanFactory#doCreateBean
=> AbstractAutowireCapableBeanFactory#populateBean
=> AutowiredAnnotationBeanPostProcessor#postProcessProperties

源代码分析

1.AutowiredAnnotationBeanPostProcessor#postProcessProperties

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
       // 这里获取目标bean每个需要注入的依赖,metadata会包含一组元素,每个元素对应一个目标bean :
       // 1. @Autowired/@Value 注解的属性 或者
       // 2. @Autowired/@Value 注解的方法参数
		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;
	}

2.InjectionMetadata#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()) {
			// 遍历目标bean每个需要注入的成员属性依赖或者成员方法参数依赖,执行相应的依赖注入
			for (InjectedElement element : elementsToIterate) {
				if (logger.isTraceEnabled()) {
					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
				}
				element.inject(target, beanName, pvs);
			}
		}
	}

3.InjectedElement#inject

3.1 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 {
				Class<?>[] paramTypes = method.getParameterTypes();
				arguments = new Object[paramTypes.length];
				DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
				Set<String> autowiredBeans = new LinkedHashSet<>(paramTypes.length);
				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 {
						// 依赖解析使用 beanFactory#resolveDependency
						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);
					}
				}
				synchronized (this) {
					if (!this.cached) {
						if (arguments != null) {
							Object[] cachedMethodArguments = new Object[paramTypes.length];
							System.arraycopy(descriptors, 0, cachedMethodArguments, 0,
									 arguments.length);
							registerDependentBeans(beanName, autowiredBeans);
							if (autowiredBeans.size() == paramTypes.length) {
								Iterator<String> it = autowiredBeans.iterator();
								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();
				}
			}
		}

3.2 AutowiredFieldElement#inject

成员属性依赖注入 :

		@Override
		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 {
					// 依赖解析使用 beanFactory#resolveDependency
					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);
			}
		}

从上面的代码可见,最终成员属性/成员方法参数依赖的解析最终都是通过BeanFactory#resolveDependency。关于BeanFactory#resolveDependency如何工作,可以参考"Spring 依赖解决过程分析"。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值