@Autowired实现自动装配的原理

        我们大家都知道,Spring容器会管理bean,而 不需要开发者自己手动注入,从而达到了解耦的目的。我们经常使用注解@Autowired实现spring的自动注入,那么@Autowired能够实现自动注入的原理是什么样的呢?今天我们就来通过源码看下具体的实现方式。

1. 注解本身如何在代码中起作用的

        首先大家要知道,注解本身本身并没有什么逻辑,把注解放在类上或者属性上,只能说明这个类或者这个属性上有这样一个名叫xxx的注解。就像是猪肉,国标的猪肉会给猪肉上边盖一个章,而这个章只是一个标记,而这个章并没有改变猪肉本身。但是我们的分拣员看到有章的猪肉,就会把该猪肉分发到正规的渠道,而没有章的猪肉就做其他处理。我们的注解其实和章是一个概念,只是起到了标记的作用,而真正起作用的是注解解析器,而注解解析器就好比是分拣员,会对有该注解的类做相应的逻辑处理。

2. @Autowired的注解解析器

        这里就不卖关子了,@Autowired的注解解析器是AutowiredAnnotationBeanPostProcessor。该类的继承类图如下:

通过继承类图可以看到,AutowiredAnnotationBeanPostProcessor类间接实现了InstantiationAwareBeanPostProcessor,而InstantiationAwareBeanPostProcessor又实现了BeanPostProcessor。

        BeanPostProcessor接口,如果对spring有一定了解的同学一定对这个接口不陌生,这个接口是Spring为开发者提供的扩展点,BeanPostProcessor有两个方法,postProcessBeforeInitialization和postProcessAfterInitialization,分别在bean初始化前执行postProcessBeforeInitialization发放和初始化后执行postProcessAfterInitialization方法。那InstantiationAwareBeanPostProcessor又有什么用处呢?

       InstantiationAwareBeanPostProcessor接口有postProcessBeforeInstantiation、postProcessAfterInstantiation和postProcessProperties三个方法。注意,不要把前两个方法跟BeanPostProcessor的两个方法搞混淆了,前者的方法名是以Instantiation结尾,而后者的方法名是以Initialization结尾(之前我就给看成一个了)。本篇文章重点关注的postProcessProperties方法。

3. bean创建

       说到依赖注入,当然要先说下bean创建了,要不然没有bean的创建,哪来的依赖注入呢?

        因为bean创建不是本篇文章的重点,所以简要说下。

这里引用一篇别人的文档解释说明一下spring启动和bean创建的过程:

https://www.jianshu.com/p/927f24ceadfa

       spring中绝大多数的bean都要通过如下doGetBean的代码进行创建       

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

     代码中有这样一段代码

try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}

其中,initializeBean方法是启动bean的初始化方法,而populateBean方法是给对象中的属性赋值,可以看出来,给属性赋值是要早于bean的初始化的(注意,初始化不等于实例化,初始化是bean声明周期的一个阶段,实例化只是调用了class的构造方法,相当于new )。

        这篇文章主要关注属性赋值,所以我们看populateBean方法的代码:

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 (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						return;
					}
				}
			}
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

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

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

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			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;
				}
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, 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;
				}
			}

这段代码的意思就是首先获取到spring中所有实现了 BeanPostProcessor接口的类,并循环逐个处理,如果某个BeanPostProcessor实现类又实现了InstantiationAwareBeanPostProcessor,则调用其postProcessProperties方法,这里就是调用@Autowired的注解解析器AutowiredAnnotationBeanPostProcessor中的postProcessProperties方法,这个方法的主要目的就是对属性进行注入。

代码如下:

@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		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,另一个是metadata.inject(bean, beanName, pvs)。其中,前者就是通过反射机制找到该对象所有标注了@Autowired注解的属性或方法等,并以InjectionMetadata对象返回,后者就是通过metadata对象对相关属性进行属性注入。

        当然,整个过程还是比较复杂的,比如注入的对象还没有生成、存在循环依赖等问题,spring是很强大、很复杂的系统,我们只能每一篇文章梳理某一个点。

       这里引用另外一位作者的博客https://blog.csdn.net/topdeveloperr/article/details/87971446?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task,觉得写得好不错,两篇文章可以结合一起 看哦。

       学海无涯,让我们一起加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值